-1

I have created a multi-select combobox in LWC, passing list of columns to it from the parent components. Its a json which is being passed from parent to child. JSON :

[{"align":"left","columnOrder":4,"label":"Code","name":"code","resize":true,"width":50,"selected":false,"min_width":50},
{"align":"left","columnOrder":5,"editor":{"type":"text","map_to":"text"},"label":"Order Item Name","name":"text","resize":true,"tree":true,"width":250,"selected":true}]

Below is code for the dropdown

<div class="slds-dropdown slds-dropdown_length-5 slds-dropdown_fluid" id="5" onmouseenter={handleMouseEnter}
    onmouseleave={handleMouseleave} role="listbox">
    <ul class="slds-listbox slds-listbox_vertical" role="presentation">
        <template for:each={inputOptions} for:item="option">
            <li class="slds-listbox__item" data-selected="false" data-id={option.name} data-value={option.name}
                key={option.name} role="presentation" onclick={handleSelection}>
                <div class="slds-media slds-listbox__option slds-listbox__option_plain slds-media_small slds-is-selected"
                    role="option" aria-checked="true">
                    <span class="slds-media__figure">
                        <lightning-icon
                            class="slds-icon-utility-check slds-current-color slds-listbox__icon-selected slds-icon_container"
                            icon-name="utility:check" size="x-small">
                        </lightning-icon>
                    </span>
                    <span class="slds-media__body">
                        <span class="slds-truncate" title={option.label}>{option.label}</span>
                    </span>
                </div>
            </li>

        </template>
    </ul>
</div>

In the JSON, I have an attribute selected, this is being set to true or false from the parent component, what I need to do is whenever the selected is true, only for that value I need to add the slds-is-selected class, else remove it.

In the JS, I am trying to apply below logic

this.inputOptions.forEach((opt) => {
    if (!opt.selected) {
        let listBoxOptions = this.template.querySelectorAll('.slds-listbox__option');
        for (let option of listBoxOptions) {
            console.log('inside for loop');
            option.classList.remove("slds-is-selected"); // Using this it will remove for all
        }
    }
});

But since using this.template.querySelectorAll, it returns all, so it will either add or remove all of it. How do I conditionally add/remove for each?

1 Answer 1

1

I was able to get this to work using below logic in the JS

this.inputOptions.forEach((opt) => {
    console.log(opt.selected);
    if (!opt.selected) {
        let listBoxOptions = this.template.querySelectorAll('.slds-listbox__option');
        let classListVar = listBoxOptions[this.inputOptions.indexOf(opt)].classList;
        classListVar.remove("slds-is-selected");
    }
});

Edit : Have another simpler solution for this one, since there is already a boolean selected attribute, I have used the template directive to conditionally render checked/unchecked in the dropdown. So we no longer need the above piece of code.

<template if:true={option.selected}>
   <div class="slds-media slds-listbox__option slds-listbox__option_plain slds-media_small slds-is-selected">
   </div>
</template>

<template if:false={option.selected}>
   <div class="slds-media slds-listbox__option slds-listbox__option_plain slds-media_small">
   </div>
</template>
3
  • this is not very good approach to a simple use case, you already have a selected attribute in your JSON, so, you can either use a template directive to conditionally render a checked or unchecked element. All you need to do is make sure that when you select/toggle the checkbox, your array of objects is properly mutated to trigger a re-render, and instead let your template directive take charge of displaying a checked or unchecked element. less code to maintain, les complicated logic, less prone to mistakes, and easier to test for, however, it doesn't look like you unit test your js code.
    – glls
    Commented Feb 3, 2022 at 18:34
  • @glls - I had already updated my code using template directive instead of the above solution I mentioned and it works as needed. My bad I did not update the solution out here. Thank you for your comment.
    – Rohit
    Commented Feb 3, 2022 at 18:54
  • Glad you were able to change that, you should probably update your solution as well
    – glls
    Commented Feb 3, 2022 at 18:55

You must log in to answer this question.

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