[BUG] MultiSelect does not contain the prop 'optionLabel'

UI Components for React
Post Reply
rvw
Posts: 12
Joined: 01 Jun 2018, 10:48

12 Jun 2018, 11:24

There's no optionLabel to be found in the props of the MultiSelect:

Code: Select all

interface MultiSelectProps {
    id?: string;
    value?: any;
    options?: Array<any>;
    style?: object;
    className?: string;
    scrollHeight?: string;
    defaultLabel?: string;
    disabled?: boolean;
    filter?: boolean;
    key?: string;
    itemTemplate?(): void;
    onChange?(e: {originalEvent: Event, value: any}): void;
    appendTo?: HTMLElement;
}

rvw
Posts: 12
Joined: 01 Jun 2018, 10:48

12 Jun 2018, 11:48

Another bug found with the MultiSelect:

itemTemplate does not get the option

Problem:

Code: Select all

interface MultiSelectProps {
    ...
    itemTemplate?(): void;
    ...
}
I tried changing it to

Code: Select all

itemTemplate?(e): void;
, which returns the option so I can customize the text visible in the dropdown BUT it'll break the onChange function and the filter function:
onChange => e.value will be an array of undefined: [undefined]
Trying to filter gives the error:

Code: Select all

Uncaught TypeError: Cannot read property 'toLowerCase' of undefined
    at MultiSelect.filterOption

rvw
Posts: 12
Joined: 01 Jun 2018, 10:48

12 Jun 2018, 12:24

Filter somewhat fixed. Problem was that I did not specify an optionLabel (I'm using custom options object and itemTemplate). Would be better if there would be a filterBy, like described in the DropDown element documentation https://www.primefaces.org/primereact/#/dropdown. (I noticed that filterBy is described on the page itself, but the prop is not to be found in the properties table, nor it is in the properties in the code.)
Options can be filtered using an input field in the overlay by enabling the filter property. By default filtering is done against label of the SelectItem and filterBy property is available to choose one or more properties of the SelectItem API.

rvw
Posts: 12
Joined: 01 Jun 2018, 10:48

12 Jun 2018, 13:34

Last bug I found for now: I worked around bugs above by changing my object, adding another field to it and choosing that field as optionLabel

Everything works this way, and in the multiselect the values that are chosen, are selected.
Only the label text shows null. This is because of this piece of code:

Code: Select all

{
        key: 'findLabelByValue',
        value: function findLabelByValue(val) {
            var label = null;

            for (var i = 0; i < this.props.options.length; i++) {
                var option = this.props.options[i];
                var optionValue = this.getOptionValue(option);

                if (optionValue === val) {
                    label = this.getOptionLabel(option);

                    break;
                }
            }

            return label;
        }
More precise:

Code: Select all

if (optionValue === val) {
    label = this.getOptionLabel(option);

    break;
}
I console logged both values and the val object contains a field _$visited, so it'll never get into the if statement and label will always be null.

EDIT: Apparently you have a function to compare 2 objects already so change

Code: Select all

if (optionValue === val)
to

Code: Select all

if (_ObjectUtils2.default.equals(optionValue, val))

rvw
Posts: 12
Joined: 01 Jun 2018, 10:48

12 Jun 2018, 14:27

Last post:
it would be nice if
1. we could choose which fields of an object would show in the dropdown, divided by either a self chosen delimiter or a default one. So something like this

Code: Select all

<MultiSelect optionLabels="code,description" />
// => Code: description

<MultiSelect optionLabels="code,description" delimiter=" - " />
// => Code - description
2. We could choose which field would be added to the label once selected

Code: Select all

<MultiSelect optionLabels="code,description" delimiter=" - " selectedOptionLabel="code" />
// => 1, 3
// => DROPDOWN
// => V | 1 - description
// =>     | 2 - description
// => V | 3 - description

I changed the code a little bit so I could achieve what I wanted:

Code: Select all

key: 'findLabelByValue',
value: function findLabelByValue(val) {
    var label = null;

    for (var i = 0; i < this.props.options.length; i++) {
        var option = this.props.options[i];
        var optionValue = this.getOptionValue(option);

        if (_ObjectUtils2.default.equals(optionValue, val)) {
            label = this.getOptionLabel(option, true);
            break;
        }
    }
    
    return label;
}
        
        
CHANGED THIS
if (_ObjectUtils2.default.equals(optionValue, val)) { // See above
    label = this.getOptionLabel(option, true); // Altered function, see below
    break;
}

Code: Select all

key: 'getOptionLabel',
value: function getOptionLabel(option, useSelectedOptionLabel = false) { // Added support for a selected option label
    // If a selectionOptionLabel is given to MultiSelect element, and we're attaching to the selected label, use selectedOptionLabel
    if (this.props.selectedOptionLabel && useSelectedLabel) return _ObjectUtils2.default.resolveFieldData(option, this.props.selectedOptionLabel)
    return this.props.optionLabel ? _ObjectUtils2.default.resolveFieldData(option, this.props.optionLabel) : option.label;
}

Code: Select all

interface MultiSelectProps {
    ....
    optionLabel?: string;
    selectedOptionLabel?: string;
    ....
}
You can use this code, but a solution would be nice


3. A filter/toggle button where we can specify to only show the selected items in the dropdown

Post Reply

Return to “PrimeReact”

  • Information
  • Who is online

    Users browsing this forum: No registered users and 11 guests