0

I'm fairly new to LWC coming from Aura. This may be a simple question.

I have a list on my main component with child-component items. Clicking these, sets another child-component (selectedTask). I need to add .slds-is-selected class to the LI element when firing the onSelect event on the component, and removing it when selecting another. My problem is identifying the LI item from the event and key, as well as adding and removing the class.

<template>
    <div class="slds-grid slds-gutters">
        <template if:true={_wiredCaseResult.data}>
        <lightning-card title='Sagsopgaver' style="width:300px" icon-name="standard:product_required" class="slds-m-left--small slds-m-right--small">
            <lightning-layout class="slds-var-m-around_medium">
                <template if:true={_wiredTaskResult.data}>
                    <ul class="slds-list--vertical slds-has-cards slds-has-block-links--space slds-has-list-interactions">
                        <template for:each={_wiredTaskResult.data} for:item="task">
                            <li key={task.Id} class="slds-list__item">
                            <c-production-task-list-item task={task}
                                onselect={handleSelect}></c-production-task-list-item>
                            </li>
                        </template>
                    </ul>
                </template>
            </lightning-layout>
        </lightning-card>
    </template>
        <template if:true={selectedTask}>
            <c-production-task-details style="width:100%" class="slds-m-right--small" task={selectedTask} onupdate={updateHandler}>
            </c-production-task-details>
        </template>
    </div>
</template>
    
    
    handleSelect(event) {
        const taskId = event.detail;
        this.selectedTask = this._wiredTaskResult.data.find(
              (task) => task.Id === taskId
            );
         }

Edit: added more code

Edit 2: I ended up with this solution in the eventhandler

  handleSelect(event) {
    // handle selected class on list items
    var _listItem = event.currentTarget.parentNode; // this is the <LI>
    var _listItems = _listItem.parentNode.childNodes; // this is every <LI> in the <UL>
    for (var i = 0; i < _listItems.length; i++) {
      _listItems[i].classList.remove("slds-is-selected");
    }
    _listItem.classList.add("slds-is-selected");

    const taskId = event.detail;
    this.selectedTask = this._wiredTaskResult.data.find(
      (task) => task.Id === taskId
    );
  }
2
  • Don't manipulate the DOM manually (adding classes), there's not guarantee that LWC will not rerender the component without your changes.You can do manual DOM selection in specific cases but you need to identify these parts of the DOM tree with a special lwc:dom="manual" tag. It's not recommended for your use case.
    – POZ
    Jan 19, 2021 at 15:34
  • @POZ Thanks, I will look into that. Appreciate your help and feedback. Jan 20, 2021 at 9:03

1 Answer 1

0

If your list and its items are in the same component (no child component), you'll need to store the list item classes in the list data itself. This works but it's cumbersome.

If you down this path, you'll need a new classes property on your task like this:

<li key={task.Id} class={task.classes}>

You'll need to update the list data when the user makes a selection:

handleSelect(event) {
    // TODO: copy list data.
    // For each list item, fill a 'classes' string attribute with either
    // 'slds-list__item' if the item is not selected
    // 'slds-list__item slds-is-selected' if the item is selected
}

That being said, it will be easier to split the list from the list items by creating a child component. If you do this, you won't need to modify the list data and you can handle the selection state in the sub-component.

Check out the LWC Recipes sample app for some ideas on how to do this.

2
  • I've edited and included all of the "parent". I have the items in a child component, which gets iterated from the list of items in the parent. The details of the selected child in a details card. Edit: hit Enter in comment... twice.. Do you suggest to put the whole list in a child component? Jan 19, 2021 at 11:15
  • I see that you've created a c-production-task-list-item child component and that's great. You just need to add an extra selected-id={selectedTask} attribute to it. This will let you adjust the style of the list item. In that case, no need to modify the list data at all.
    – POZ
    Jan 19, 2021 at 15:38

You must log in to answer this question.

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