salesforce / lwc

⚡️ LWC - A Blazing Fast, Enterprise-Grade Web Components Foundation
https://lwc.dev
Other
1.63k stars 393 forks source link

Lightning-datatable has wrong type of parameters passed to custom type columns through typeAttributes that passsed not with "fieldName" #4177

Open Paul-Kalynyn opened 6 months ago

Paul-Kalynyn commented 6 months ago

Description

I have created custom type for editing Picklist values of records using lightning-combobox. Inside its template it uses typeAttributes.options for options attribute. But if you specify in column configuration "typeAttributes" : { "options" : [ option1, options2 ]} then it will pass to actual options of lightning-combobox not the specified array, but an object { "0" : option1, "1": option2 }. And then under the hood lightning-combobox will ignore it and use empty array for options. But if you specify column configuration with "typeAttributes" : { "options" : { "fieldName" : "actionFieldName" } and then modify all rows of data for datatable by adding field "actionFieldName" that will contains expected options [ option1, option2 ] as value - it will work as expected, but this kind of configuration can be called workaround.

Steps to Reproduce

  1. Create LWC that extend LightningDatatable.
  2. Create custom type with edit template for lightning-datatable.
  3. Use lightning-combobox inside this template with {typeAttributes.options} as value for options attribute:
    <template>
    <lightning-combobox
        name="customCombobox"
        data-inputable="true"
        label={typeAttributes.label}
        value={editedValue}
        placeholder={typeAttributes.placeholder}
        options={typeAttributes.options}
        variant="label-hidden"
        dropdown-alignment="auto">
    </lightning-combobox>
    </template>
  4. For static customTypes variable of created LWC use this:
    customCombobox : {
    template: customComboboxTemplate,
    editTemplate: customComboboxEditTemplate,
    typeAttributes: [ 'label', 'placeholder', 'options', 'value' ],
    standardCellLayout: true
    }
  5. Create LWC that will use this LWC as datatable and add column with created custom type:
    {
    label: 'Custom Picklist',
    fieldName: 'picklistData',
    type: 'customCombobox',
    typeAttributes: {
        label: 'Custom Picklist',
        placeholder: 'Choose Value...',
        options: [ {
            { label: 'Option 1', value: 'option1' },
            { label: 'Option 2', value: 'option2' }
        }],
        value: { fieldName : 'picklistData' }
    },
    hideDefaultActions: true,
    editable : true
    }

Expected Results

When you pass data to this custom lwc and clicks on edit button near "Custom Picklist" column value, then combobox appears with ability to choose between "Option 1" and "Option 2".

Actual Results

Combobox appears with no options to select

Version

SF Api version 60.0

KeithClarke commented 5 months ago

I'm seeing this trying to pass options to a lightning-dual-listbox. I'm using your work-around @Paul-Kalynyn pending a fix.

Paul-Kalynyn commented 5 months ago

@KeithClarke i am using new workaround right now that allows you to pass options for custum picklist in column typeattributes as expected. You can create custom component that will have on public attribute for options and it will convert it from array like object to actual array. And then it will pass it to lightning combobox that is placed inside this component as slot. I mean in your edit template for datatable it will looks like this:

<template>
    <c-combobox-wrapper options={typeAttribute.options}>
        <lightning-combobox ...></lightning-combobox>
    </c-combobox-wrapper>
</template>
britishboyindc commented 5 months ago

I hit this issue as well - another option I found was to use a custom setter on the option value, and convert e.g. set options(value) { if (value) { this._options = Object.values(value); } }

But the other challenge here is that this issue only seems to arise when you pass in the options directly as opposed to a field level attribute. But if you always plan to use this approach, the object.values seems to work