[SalesForce] LWC: Get Button Element in JavaScript from LWC

Scenario: I have a LWC with a lightning-button which calls an action in the JS controller. Within the JS controller, I am trying to target the button element and update it's innerHTML and/or update it to disabled=true.


Per the Salesforce LWC Documentation "Access Elements the Component Owns":

To access elements rendered by a component, use the template property.

this.template.querySelector();

this.template.querySelectorAll();

and per How to migrate aura:id to Lightning Web Components data-id acts as the LWC equivilent of aura:id from Aura components.


So, following that guidance, I added a data-id to a lightning-button in my markup:

<template if:true={showSendSignature}>
    <lightning-button name="Send for Signature" data-id="adobeSignBtn" variant="success" label="Send for Signature" onclick={adobeSendForSignature} ></lightning-button>  
</template>

In my JavaScript, I then do:

const adobeButton = this.template.querySelector('[data-id="adobeSignBtn"]');
console.log(adobeButton);

When I inspect the page, I notice that the data-id is actually on a parent element to the button itself, rather than on the button element:

<lightning-button c-alphacreateorderform_alphacreateorderform="" data-id="adobeSignBtn"
    <button name="Send for Signature" type="button" class="slds-button slds-button_success slds-button_first">Send for Signature</button>
</lightning-button>

In console, adobeButton returns SecureElement: [object HTMLElement]

When I do console.log(adobeButton.childNodes), I get back SecureNodeList: [object NodeList]

However, when I do adobeButton.childNodes[0], I get undefined


Question: How do I correctly access this button in a LWC JS controller?

Best Answer

Both querySelector and Event.target will refer to the element so you can do the following with them.

Access the disabled attribute directly:

const adobeButton = this.template.querySelector('[data-id="adobeSignBtn"]');
adobeButton.disabled = true;
handleButtonClick(event){
    event.target.disabled = true;
}

You're not just limited to the attributes, you can do more on the element like styles

const adobeButton = this.template.querySelector('[data-id="adobeSignBtn"]');
adobeButton.style.visibility = 'hidden';
handleButtonClick(event){
    event.target.style.visibility = 'hidden';
}

You can also interact with the class of the element

const adobeButton = this.template.querySelector('[data-id="adobeSignBtn"]');
adobeButton.className += " slds-hide";
handleButtonClick(event){
    event.target.className += " slds-hide";
}

You can see this all of these in the following playground.