[SalesForce] LWC querySelectorAll is not working

I am trying to iterate Student name as a button on click of button i need to show the students details below.

For this, by default i kept the button class as slds-button_neutral on click of any of the student i need to change the button type to slds-button_brand

For Example:
Iteration of the student

Student 1         Student 2           Student 3

All student button slds style will be will be slds-button_neutral.

If i click the Student 2, button slds style will be changed as slds-button_brand for Student 2. Student 1 and 3 will remains the same style. End user want's to know which student i selected.

To achieve this i wrote the below code, I don't see any error, But It's not working, Can any one help what is that I am missing here.

HTML

 <template for:each={contactSearchList} for:item="family" for:index="index">
             
            <div key={family.id}
                class="slds-p-around_none slds-m-top_x-small slds-m-bottom_medium slds-m-horizontal_none">
                <lightning-layout>
                    <template for:each={family.student} for:item="student" for:index="index">
                        <lightning-layout-item key={student.id} flexibility="auto" padding="around-small">
                            <div class="  slds-p-around_medium slds-text-align_center">
                                <button class="slds-button slds-button_neutral studentButton" name="studentInfo_btn"
                                    data-isactive="false" onclick={handleselectStudent}>{student.lastName}
                                    <span class="slds-p-right_x-small"></span>
                                    {student.firstName}</button></div>
                        </lightning-layout-item>

                    </template>
                </lightning-layout>
            </div>

        </template>

JS

 handleselectStudent(event) {
const studentInfobtns = this.template.querySelectorAll(
      "button.slds-button slds-button_neutral studentButton"
    );
    alert(studentInfobtns + "" + studentInfobtns.length);
    if (
      studentInfobtns.length !== undefined &&
      studentInfobtns.length != null
    ) {
      alert("first if");
      studentInfobtns.forEach((studentInfobtn) => {
        studentInfobtn.className = "slds-button slds-button_brand";
      });
    }
}

Best Answer

It is not recommended to manipulate the DOMs using Javascript, because the LWC run time does it in a very efficient manner. If you use the javascript properties, you can achieve this like below.

Pass in the unique id of the student and family as data attributes to the button like below. You also need a property on each student record to set the class dynamically.

<div key={family.id} class="slds-p-around_none slds-m-top_x-small slds-m-bottom_medium slds-m-horizontal_none">
    <lightning-layout>
        <template for:each={family.student} for:item="student" for:index="index">
            <lightning-layout-item key={student.id} flexibility="auto" padding="around-small">
                <div class="  slds-p-around_medium slds-text-align_center">
                    <button data-student-id={student.id} data-family-id={family.id} class={student.buttonClass} name="studentInfo_btn"
                        data-isactive="false" onclick={handleselectStudent}>{student.lastName}
                        <span class="slds-p-right_x-small"></span>
                        {student.firstName}</button></div>
            </lightning-layout-item>

        </template>
    </lightning-layout>
</div>

Note: If you are using the standard Id field, the I is capital in it like Id and not 'id' which you have in the code, so consider changing if needed.

Then in the handler based on the button, you can manipulate the js property.

// make sure the list contactSearchList is annotated with the @track attribute.
handleselectStudent(event){
     let familyId = this.contactSearchList.findIndex(event.dataset.familyId);
     this.contactSearchList[familyId].forEach( student => {
         if(student.id === event.target.dataset.studentId){
              student.buttonClass = 'slds-button slds-button_brand studentButton';
         } else {
             student.buttonClass = 'slds-button slds-button_neutral studentButton';
         }
     })
}

Everytime you load the data, you will need to set the default class to slds-button slds-button_neutral studentButton in wire/imperative apex.

Related Topic