0

multiSelectcombobox HTML :

    <template>
    <div class="slds-form-element">
      <label if:true={label} class="slds-form-element__label">
        <abbr if:true={required} title="required" class="slds-required">*</abbr>
        {label}</label
      >
      <div class="slds-form-element__control">
        <div class="slds-combobox_container">
          <div
            class="slds-combobox slds-dropdown-trigger slds-dropdown-trigger_click slds-picklist multi-select-combobox__dropdown"
          >
            <div class="slds-combobox_form-element slds-input-has-icon slds-input-has-icon_right" role="none">
              <input
                class="slds-combobox__input multi-select-combobox__input"
                aria-controls="multi-pick-list-dropdown-items"
                role="textbox"
                type="text"
                value={selectedItems}
                required={required}
                disabled={isDisabled}
                readonly
              />
              <span
                class="slds-icon_container slds-icon-utility-down slds-input__icon slds-input__icon_right multi-select-combobox__icon"
                title="Click to open the dropdown"
              >
                <lightning-icon
                  icon-name="utility:down"
                  size="xx-small"
                  alternative-text="Click here"
                  class="slds-icon slds-icon--selected slds-icon--x-small slds-icon-text-default"
                >
                </lightning-icon>
              </span>
            </div>
            <div
              class="slds-dropdown slds-dropdown_length-5 slds-dropdown_fluid multi-select-combobox__listbox"
              role="listbox"
            >
              <ul class="slds-listbox slds-listbox_vertical" role="presentation">
                <template for:each={currentOptions} for:item="item">
                  <c-multi-select-combobox-item key={item.value} item={item} onchange={handleChange}>
                  </c-multi-select-combobox-item> 
                </template>
              </ul>
            </div>
          </div>
        </div>
      </div>
      <div if:true={hasPillsEnabled}>
        <lightning-pill-container
          if:true={isVisible}
          items={selectedOptions}
          variant="bare"
          onitemremove={handleRemove}
        ></lightning-pill-container>
      </div>
    </div>
  </template>

multi select combobox JS :

renderedCallback() {

    if (!this.isInitialized) {
      this.template.querySelector('.multi-select-combobox__input').addEventListener('click', (event) => {
        this.handleClick(event.target);
        event.stopPropagation();
      });
      this.template.addEventListener('click', (event) => {
        event.stopPropagation();
      });
      document.addEventListener('click', () => {
        this.close();
      });
      this.isInitialized = true;
      this.setSelection();
    }
  }
  handleChange(event) {
    this.change(event);
  }
  handleRemove(event) {
    this.selectedOptions.splice(event.detail.index, 1);
    this.change(event);
  }
  handleClick() {
    // initialize picklist options on first click to make them editable
    if (this.isLoaded === false) {
      this.currentOptions = JSON.parse(JSON.stringify(this.options));
      this.isLoaded = true;
    }
    console.log('Firas04',this.currentOptions);
    if (this.template.querySelector('.slds-is-open')) {
      this.close();
    } else {
      this.template.querySelectorAll('.multi-select-combobox__dropdown').forEach((node) => {
        node.classList.add('slds-is-open');
      });
    }
  }
  change(event) {
    // remove previous selection for single select picklist
    let xxx;
    if (this.singleSelect) {
      this.currentOptions.forEach((item) => (item.selected = false));
    }
    // set selected items
    this.currentOptions
      .filter((item) => item.value === event.detail.item.value)
      .forEach((item) => (item.selected = event.detail.selected));
    this.setSelection();
    
    const selection = this.getSelectedItems();
    this.passvalues = selection.map((selected) => selected.label).join(', ');
    console.log('selection CHANGEE',this.passvalues);
    
    this.dispatchEvent(new CustomEvent('change', { detail: this.singleSelect ? selection[0] : selection }));
    // for single select picklist close dropdown after selection is made
    if (this.singleSelect) {
      this.close();
    }
  }
  close() {
    this.template.querySelectorAll('.multi-select-combobox__dropdown').forEach((node) => {
      node.classList.remove('slds-is-open');
    });
    this.dispatchEvent(new CustomEvent('close'));
  }
  setSelection() {
    const selectedItems = this.getSelectedItems();
    let selection = '';
    if (selectedItems.length < 1) {
      selection = this.placeholder;
      this.selectedOptions = [];
    }  else {
      selection = selectedItems.map((selected) => selected.label).join(', ');
      this.selectedOptions = this.getSelectedItems();
    }
    this.selectedItems = selection;
    this.isVisible = this.selectedOptions && this.selectedOptions.length > 0;
    console.log('selection',selection);

  }

  getSelectedItems() {
    return this.currentOptions.filter((item) => item.selected);
  }

MultiSelectComboboxItem Js :

import { api, LightningElement } from 'lwc';

export default class MultiSelectComboboxItem extends LightningElement {
  @api item;

  connectedCallback () {
    this._item =  JSON.parse(JSON.stringify (this.item));
}
  get itemClass() {
    return `slds-listbox__item ${this.item.selected ? 'slds-is-selected' : ''}`;
  }

  handleClick() {
    this.dispatchEvent(
      new CustomEvent('change', {
        detail: { item: this.item, selected: !this.item.selected }
      })
    );
  }
}

Parent component Js :

@wire( getPicklistValues, { recordTypeId: '$objectInfo.data.defaultRecordTypeId', fieldApiName: STATUS_FIELD } )
    picklistValues;
       handleValueChange(event) {
            const { index, field } = event.target.dataset;
            var value =    event.detail.childfilter || event.target.value  || event.detail;
            this.caseDefaultData[index][field] = value;
            
            if(event.detail != null){
            this.selectedOptions = event.detail.value;
           
            
            console.log( 'Helloooo this.selectedOptions000', JSON.stringify(this.selectedOptions) );
        }
        
            if ( event.target.dataset.id == 'fielD' && value == 'Contact') {
                value = event.detail.childfilter ;
               // this.showLookupSearch = true;
                this.caseDefaultData[index]['lookupContact']=true;
                this.input4 = 'Account';          
           //     console.log('VALUEE',value);
               
            }
            
           else if ( event.target.dataset.id == 'fielD' && value == 'AccountId') {
                value = event.detail.childfilter ;
               // this.showLookupSearch = true;
                this.caseDefaultData[index]['showLookupSearch']=true;
                this.caseDefaultData[index]['lookupContact']=false;
                this.input4 = 'Account';          
           //     console.log('VALUEE',value);
               
            }else if(event.target.dataset.id == 'fielD' && value != 'AccountId') {
                
                if(event.target.dataset.id == 'fielD' && value == 'Status'  ){
                    console.log( 'Helloooo' );
                   
                    
                   value = JSON.stringify(event.target.value) ;
                   console.log( 'Helloooo vvv',value );
                   this.caseDefaultData[index]['showLookupSearch']=false;
                   this.caseDefaultData[index]['picklistField']=true;
                    console.log( 'this.showLookupSearch',this.showLookupSearch );
                   
                    console.log( 'this.picklistField',this.picklistField );
                } else {
                    this.caseDefaultData[index]['showLookupSearch']=false;
                    this.caseDefaultData[index]['picklistField']=false;
                    this.caseDefaultData[index]['lookupContact']=false;
                    value = event.target.value ;

                   
                }
            

            }

Parent HTML :

 <template for:each={caseDefaultData}  for:item="acc"  for:index="index">
                            <tr key={acc.index} id={acc.index} > 
                                <td>Filtre #{acc.rowNumber}</td>   
                                <td>
                                    <lightning-combobox 
                                    data-index={index}
                                    data-field="Field__c"
                                    data-id="fielD"
                                    name="input1" 
                                    label="Field"
                                    placeholder="Sélectionner un champ" 
                                    value={acc.Field__c} 
                                    onchange={handleValueChange} 
                                    options={Options}>
                                    </lightning-combobox>
                                </td>
                                 
                                
                                <td style="padding-top:40px">  <lightning-input-field data-field="Operator__c" data-index={index} data-id={acc.index} field-name="Operator__c" value={acc.Operator__c} name="input2" onchange={handleValueChange} ></lightning-input-field></td>
                                
                               <template  if:true={acc.lookupContact}>
                                    <td> showLookupSearch = {acc.showLookupSearch} picklistField = {acc.picklistField} <c-lookup-search data-field="Value__c"   value={acc.Value__c}   selectedsobject="Contact" onsearchstringvaluechange={handleValueChange}    data-index={index} data-id={acc.index} label="Custom Lookup - Account"   selected-name={acc.Value__c}  recordlimit="10" onlookupselect={handlelookupselectaccount} ></c-lookup-search>  </td>
                                </template>
                               
                                <template  if:false={acc.lookupContact}>
                                    <template  if:true={acc.showLookupSearch}>
                                        <td> showLookupSearch = {acc.showLookupSearch} picklistField = {acc.picklistField} <c-lookup-search data-field="Value__c"   value={acc.Value__c}   selectedsobject="Account" onsearchstringvaluechange={handleValueChange}    data-index={index} data-id={acc.index} label="Custom Lookup - Account"   selected-name={acc.Value__c}  recordlimit="10" onlookupselect={handlelookupselectaccount} ></c-lookup-search>  </td>
                                    </template>
                                        <template  if:false={acc.showLookupSearch}>
                                            <template  if:true={acc.picklistField}>
                                                <template  if:true={picklistValues.data}>
                                                    <td> showLookupSearch = {acc.showLookupSearch}   picklistField = {acc.picklistField} {acc.Value__c}    <c-multi-select-combobox
                                                        label="Options01"
                                                        name="options01"
                                                        options={picklistValues.data.values}
                                                        onchange={handleValueChange}  data-field="Value__c" data-index={index}  value={acc.Value__c}  data-id={acc.index} 
                                                      ></c-multi-select-combobox> </td>
                                                </template>
                                            </template>
                                            <template  if:false={acc.picklistField}>
                                                <td>showLookupSearch = {acc.showLookupSearch}   picklistField = {acc.picklistField} <lightning-input type="text"   data-field="Value__c" data-index={index} data-id={acc.index} label="Value" value={acc.Value__c} onchange={handleValueChange} ></lightning-input>   </td>
                                            </template>
                                    </template>
                                </template>

So the combobox is showing status picklist field with multi select , but i can't understand why this.selectedOptions is showing undefined , the event.detail is showing well the attributes ..

The output of this.selectedOptions = event.detail; :

enter image description here

According to David solution :

i have changed the name of event as : this.dispatchEvent(new CustomEvent('change011', { detail: this.singleSelect ? selection[0] : selection })); and in the parent html : c-multi-select-combobox label="Options01" name="options01" options={picklistValues.data.values} onchange={handleValueChange} onchange011={handleValueChange} but the event.detail.value is still undefined

enter image description here

1
  • Please use the tools in the editor to format all of your code blocks. You can also use triple backticks (```) before and after each block. Thanks!
    – David Reed
    Commented Sep 17, 2022 at 19:01

1 Answer 1

0

Using custom events that share the names of standard events (like change) can produce surprising behavior, like you see here. That's because your handler handleValueChange() is also receiving plain old onchange events that bubble up from the <input> element (and potentially other elements within your component). Those standard events do not have a detail property, which nets you an undefined value.

There are two obvious ways to fix this issue:

  • Use a custom event that is not named change.
  • In your multi-select component, catch the change events from your embedded components and call event.stopPropagation() on them, to prevent your own parent component from receiving those events.

It appears that your code is also assuming that change events come from a single-select picklist:

this.selectedOptions = event.detail.value;

Your component sets event.detail to an array in the multi-select case:

this.dispatchEvent(new CustomEvent('change', { detail: this.singleSelect ? selection[0] : selection }));

which doesn't have a value attribute.

6
  • David , i have update the parent component code - i don't think the problem is related the name of event change because event.detail is showing attributes , but the value is undefined ..
    – Farkous
    Commented Sep 17, 2022 at 19:22
  • @Farkous He's correct. Using a standard event name causes things to behave badly. I first discovered this myself earlier in 2022. If you want to use a standard event like change, you have to do document.createEvent("htmlevents"), and set the properties.
    – sfdcfox
    Commented Sep 17, 2022 at 20:13
  • How to solve my issue ? i have changed the calling in MultiSelectCombobox this.dispatchEvent(new CustomEvent('change011', { detail: this.singleSelect ? selection[0] : selection })); and in the parent HTML : <c-multi-select-combobox onchange={handleValueChange} change011=={handleValueChange} JS : handleChange00(event) { this.selectedOptions = event.detail; this.selectedOptions = event.detail.map((selected) => selected.label).join(', '); } handleValueChange(event) { this.selectedOptions = event.detail.value; } its still un
    – Farkous
    Commented Sep 17, 2022 at 20:38
  • 1
    Your parent HTML is not valid. Event handlers need on and do not use ==.
    – David Reed
    Commented Sep 17, 2022 at 23:37
  • Yes i know i have corrected it but the this.selectedOptions it still undefined
    – Farkous
    Commented Sep 18, 2022 at 10:10

You must log in to answer this question.

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