0

I have a requirement where I have to make a checkbox checked/unchecked based on the boolean field on Case object. When I am trying to select the element using querySelector, its not returning the list of selected nodes. Am I missing something?

<template if:true={lineOfBusiness}>
    <div class="row first-selection-menu">
        <div class="first-selection-combobox">
            <h1 class="combobox-label">Line of Business</h1>
            <lightning-combobox
                label="Line of Business"
                variant="label-hidden"
                name="lineofBusiness"
                value={value}
                placeholder="Select the line of business"
                options={lineOfBusinessPicklistValues}
                onchange={handleLineBusinessChange}
            >
            </lightning-combobox>
        </div>
        <template if:true={showIsEscalated}>
            <div class="escalated-checkbox">
                <!-- Shuchi -->
                <!-- <input type="checkbox" id="escalated" name="escalated" onchange={handeEscalation} /> -->
                <input type="checkbox" data-id="escalated" name="escalated" onchange={handeEscalation}/>
                <label for="escalated" class="checkbox-label"
                    >Technical Escalation to an expert
                </label>
            </div>
        </template>
</template>

handleSelectedMain(event) {
    this.mainSelectionValue = event.target.value;
    if (this.mainSelectionValue === 'Transfer Case') {
        this.lineOfBusiness = true;
        if (this.showIsEscalated) {
            console.log(this.template.querySelector('[data-id="escalated"]'));// getting proxy object
        console.log(JSON.stringify(JSON.parse(this.template.querySelector('[data-id="escalated"]')))); // getting proxy object
                       this.template.querySelector('[data-id="escalated"]').checked = getFieldValue(
            this.caseRecord,
            ESCALATION_FLAG
        );
        }
    }
    this.showMainHelp = false;
}

Proxy object

6
  • Hello. Try this.template.querySelectorAll(). It should return a list. The querySelector() method returns the first element that matches a CSS selector.
    – Konstantin
    Mar 17, 2023 at 10:39
  • Thanks @Konstantin for your input but this also did not work. Tried below. console.log(this.template.querySelectorAll("div")); Getting Proxy like vefore Mar 17, 2023 at 11:30
  • @SHUCHITIWARI : How are you setting showIsEscalated flag ? Can you debug by removing it from both HTML & JS and check if it works ?
    – Rohit
    Mar 17, 2023 at 11:32
  • This is setting to true. I checked in debug. The flow is coming to this point. So do not understand the point of removing it. Mar 17, 2023 at 13:22
  • Then there would be some condition other than showIsEscalated due to which checkbox is not rendering. Can you post the complete HTML? I tried your code snippet and it works fine.
    – Rohit
    Mar 17, 2023 at 13:29

1 Answer 1

2

Proxy is a tool used by developers to trap certain events. Lightning Locker Service and Lightning Web Security uses a Proxy to ensure that data is accessed correctly.

As a simple demonstration to this, consider the following code:

let x = new Proxy({}, { get() { return 'Hello World'; } });
console.log(x.aMessage); // 'Hello World';
console.log(x.anotherMessage); // 'Hello World';

Here, we create a trap that always returns the same value, no matter the input.

It's helpful to note in the previous example, that running code does not see it as a Proxy:

console.log(x instanceof Proxy); // won't return true here

As far as your running code is concerned, the returned element is whatever is inside the Proxy.

With that out of the way, the next thing to note is that querySelector returns just one Element, not a NodeList that querySelectorAll would. We expect to receive a single Element wrapped in a Proxy that is transparent to the code.

However, note that there is the Component Lifecycle. Changes you make to a property are not immediately rendered as a new version, you must wait for a render cycle. setTimeout is not recommended, so your best option is to add an asynchronous wait.

We do that with a combination of async to indicate the function is wrapped in a Promise, and we use await Promise.resolve() to allow the DOM to update before continuing.

async handleSelectedMain(event) {
    this.mainSelectionValue = event.target.value;
    if (this.mainSelectionValue === 'Transfer Case') {
        this.lineOfBusiness = true;
        // Allow the DOM to update.
        await Promise.resolve();
        if (this.showIsEscalated) {
            this.isEscalatedValue = this.caseRecord.data.fields.IsEscalated.value;
            //want to check/uncheck the checkbox based on above field value. Tried using value attribute on input checkbox node and used this property      there.Not working as well
            console.log(this.template.querySelector("div")); // getting proxy object, image attached
            console.log(this.template.querySelector("input"));
            console.log(this.template.querySelector('[data-id="escalated"]')); //getting null in console
            // this.template.querySelector('[data-id="escalated"]').checked = this.caseRecordDetail.data.fields.IsEscalated.value; 
            // tried setting checked on the element but not working as element is not selected may be
        }
    }
    this.showMainHelp = false;
}
6
  • Thank you for sharing @sfdcfox , 1 question though : setTimeout is not used since it makes difficult to track page performance. How is Promise.resolve different from it and does not cause this issue?
    – Rohit
    Mar 17, 2023 at 14:33
  • 2
    @Rohit Promises themselves are still inherently synchronous, just allow for asynchronous things to happen. Here, what happens is the current event handler stops and hands control back to the lifecycle system. As soon as the render completes, JavaScript immediately comes back to our control for the rest of the handler. In that sense, it's not asynchronous. If that's not clear enough, consider what happens when you use a generator: function* range(i = 0, s = 10) { while(i < s) { yield i++; } }. This code bounces between itself and the caller, but isn't asynchronous.
    – sfdcfox
    Mar 17, 2023 at 14:37
  • Great !!! The yield example helped me to understand. I learned something new today. Thank you @sfdcfox, Upvoted the answer. This comment can also be added in the answer since it nicely explains the difference.
    – Rohit
    Mar 17, 2023 at 14:46
  • @sfdcfox Thanks for the soultion. It worked. Mar 20, 2023 at 4:58
  • @sfdcfox I am still unable to prnt that in console. It still appears as proxy. Tried JSON methods but did not work. Any suggestions? Mar 21, 2023 at 13:27

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .