7

I have a lightning button with an icon, and I want to change label, icon and CSS class when it is pressed but CSS class remains as it takes base-variant. Though icon and label are getting changed.

Markup:

<template>
        <lightning-button label={toggleButtonLabel} title="Toggle content action" 
        class="Other-Button" icon-name={toggleIconName} onclick={handleToggleClick}></lightning-button>

</template>

Javascript:

import { LightningElement, track } from 'lwc';

export default class PcSelectButtonFramework extends LightningElement {
    @track toggleIconName = 'utility:preview';
    @track toggleButtonLabel = 'Non Profit';

    // Handles click on the 'Show/hide content' button
    handleToggleClick(event) {
        // retrieve the classList from the specific element
        const contentBlockClasslist = this.template.querySelector(
            '.Other-Button'
        ).classList;
        console.log('contentBlockClasslist: '+contentBlockClasslist);
        // toggle the hidden class
        contentBlockClasslist.toggle('Submit-Button');

        // if the current icon-name is `utility:preview` then change it to `utility:hide`
        if (this.toggleIconName === '') {
            this.toggleIconName = 'utility:hide';
            this.toggleButtonLabel = 'Reveal content';
        } else {
            this.toggleIconName = 'utility:preview';
            this.toggleButtonLabel = 'Hide content';
        }


        // if the current icon-name is `utility:preview` then change it to `utility:hide`
        if (this.toggleIconName === 'utility:preview') {
            this.toggleIconName = 'utility:hide';
            this.toggleButtonLabel = 'Reveal content';
        } else {
            this.toggleIconName = 'utility:preview';
            this.toggleButtonLabel = 'Hide content';
        }
    }
}

Want to implement a related scenario like below:

enter image description here

should be changed to this (when pressed) -

[1]: https://i.stack.imgur.com/tL5Lj.png

How do I toggle CSS class on button click?

4 Answers 4

8

First off, you're on the right track.

One of the odd things with web components is this new concept of the Shadow DOM. With the Shadow DOM, you cannot style base components with either css classes or the style attribute. (Read up on the Shadow DOM here: https://developer.salesforce.com/docs/component-library/documentation/lwc/lwc.create_dom)

This means you will not be able to style the lightning-button, unfortunately. However, there's nothing stopping you from using a regular old HTML button. With that in mind, it's time to head on over to the Lightning Design System site for a code snippet. https://www.lightningdesignsystem.com/components/buttons/ provides us a few examples, including a button with an icon.

Additionally, you're slightly over complicating this logic of toggling on and off the active piece of the button. You can achieve the same functionality with a simple boolean variable and two getter methods. I took a stab at what this would look like for you below.

Another great place for some insights on lightning web components is the Trailhead Sample Gallery, so be sure to check that out if you haven't already. You can find the gallery here: https://trailhead.salesforce.com/sample-gallery

Javascript:

import { LightningElement} from 'lwc';

export default class PcSelectButtonFramework extends LightningElement {
    buttonClicked; //defaulted to false

    // Handles click on the 'Show/hide content' button
    handleToggleClick() {
        this.buttonClicked = !this.buttonClicked; //set to true if false, false if true.
    }

    get cssClass(){
        return this.buttonClicked ? 'slds-button slds-button_neutral active' : 'slds-button slds-button_neutral inactive';
    }

    get iconName(){
        return this.buttonClicked ? 'utility:hide' : 'utility:preview';
    }
}

Component:

<template>
    <button class={cssClass}>
        <lightning-icon icon-name={iconName} onclick={handleToggleClick}>Non Profit</lightning-icon>
    </button>
</template>
3
  • 1
    Out of curiosity, I tried your code and it is not working. Here is modified version of your code and it works, verified in my org. Thanks.
    – javanoob
    May 1, 2019 at 2:57
  • Forgot to add url in my previous comment : gist.github.com/sfdcale/05b7d0e8702e13081951d1e5828abc0c
    – javanoob
    May 1, 2019 at 3:08
  • @javanoob I usually try to avoid giving straight copy/pasta answers as it forces the users to adapt them. This helps keep the site away from the "do it for me" mentality.
    – gNerb
    May 5, 2019 at 14:06
3

I took the above answer from James Loghry and updated to suit your use case and here is the working code:

testLwc.html:

<template>
    <button class={cssClass} onclick={handleToggleClick}>
        <lightning-icon icon-name={iconName}></lightning-icon>
        Non Profit        
    </button>
</template>

testLwc.js

import { LightningElement, track} from 'lwc';

export default class PcSelectButtonFramework extends LightningElement {
    buttonClicked; //defaulted to false

    @track cssClass = 'slds-button slds-button_neutral';
    @track iconName = '';

    // Handles click on the 'Show/hide content' button
    handleToggleClick() {
        this.buttonClicked = !this.buttonClicked; //set to true if false, false if true.
        this.cssClass = this.buttonClicked ? 'slds-button slds-button_outline-brand' : 'slds-button slds-button_neutral';
        this.iconName = this.buttonClicked ? 'utility:check' : '';
    }
}

Here is the output in my org:

enter image description here

We are using plain button tag with lightning-icon tag and setting the iconName to blank and changing its value to check when button is clicked.

2

I haven't seen a setAttribute answer yet, so there's also that option. Simply get the element from querySelector and use the .setAttribute('class', value). It's nice if you need to set a few classes, but don't want to waste an @track variable or getter.

1

I have toggled the CSS class, and it worked for me. Please find the code please as below:

HTML:

<div class="NonSelectedBorderOrgType" onclick={toggleOrgType}>
    <img class="markIcon" src={markIcon} alt='marked'>
    <div class="pillLabel1">{type.LKUP_DSC__c}</div>
</div>

JS:

toggleOrgType(event){
const evt = event.currentTarget;
evt.classList.toggle('SelectedBorderOrgType');
evt.classList.toggle('NonSelectedBorderOrgType');
}

CSS:

 /*to show the image*/
.SelectedBorderOrgType .markIcon {
  display: block;
}
/*to hide the image*/
.NonSelectedBorderOrgType .markIcon {
  display: none;
}
.SelectedBorderOrgType .pillLabel1 {
  font-weight: 600;
}
.NonSelectedBorderOrgType{
  font-weight : normal;
}

You must log in to answer this question.

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