toystars / react-native-multiple-select

Simple multi-select component for react-native
MIT License
565 stars 313 forks source link

The props (single, selectedItems & canAddItems) don't mix! #112

Open Bilal-Abdeen opened 5 years ago

Bilal-Abdeen commented 5 years ago

Issue summary

SCENARIO DESCRIPTION: (A) The prop "single" is set to true (B) The prop "canAddItems" is set to true (C) The prop "onSelectedItemsChange" is set to {(selectedItems) => { this.setState({ selectedItems: selectedItems, }); }} (D) The prop "selectedItems" is set to {this.state.selectedItems} (1) End User selects an existing option, e.g. Green (2) End User manually enters a new option (instead of the previously selcted option), e.g. ABC

DESIRED RESULT: -> ONLY the manually eneterd option (ABC) is selcted.

ACTUAL RESULT (WHICH IS INCORRECT): -> Both options are selected (Green & ABC).

WORKAROUND: Remove the prop "selectedItems". By doing so, you lose the functionality of dynamically changing the dropdwon label (the prop "selectText") into the selected option.

To get this functionality, you can use the following code for the prop "selectText".

selectText={this.state.demo1_SelectedItems.length === 0 ? "Demo 1 Field" : this.state.demo1_SelectedItems[0]}

Library versions

expo: 32.0.0 react-native: "https://github.com/expo/react-native/archive/sdk-32.0.0.tar.gz" react-native-multiple-select: 0.5.3

Reproducible Code

import React, { Component } from 'react';
import { View } from 'react-native';
import MultiSelect from 'react-native-multiple-select';

class Screen1 extends Component {
    state = {
        demo1_SelectedItems: [],
        demo1_ItemsList: [{
            id: '11',
            name: 'Orange',
        }, {
            id: '12',
            name: 'Apple',
        }, {
            id: '13',
            name: 'Banana',
        }, {
            id: '14',
            name: 'Tomato',
        }],
    };

    demo1_OnSelectedItemsChange = (selectedItems) => {
        console.log('demo1_OnSelectedItemsChange - SelectedItems: ', selectedItems);

        this.setState({
            demo1_SelectedItems: selectedItems,
        });
    };

    demo1_OnAddItem = (newItemsList) => {
        this.setState({
            demo1_ItemsList: newItemsList,
        });
    }

    render() {
        return (
            <View>
                <MultiSelect
                    items={this.state.demo1_ItemsList}
                    uniqueKey="id"
                    displayKey="name"

                    selectText="Demo 1 Field"
                    searchInputPlaceholderText="Select or Type a value"
                    filterMethod="full"

                    single={true}
                    selectedItems={this.state.demo1_SelectedItems}

                    onSelectedItemsChange={this.demo1_OnSelectedItemsChange}

                    canAddItems={true}
                    onAddItem={this.demo1_OnAddItem}
                />
            </View>
        );
    } // end of: render
} // end of: component

export default Screen1;

WORKAROUND CODE:

                <MultiSelect
                    items={this.state.demo1_ItemsList}
                    uniqueKey="id"
                    displayKey="name"

                    // Workaround - Change#1: Replace the following line, with the one after it. 
                    // selectText="Demo 1 Field"
                    selectText={this.state.demo1_SelectedItems.length === 0 ? "Employee's Role" : this.state.demo1_SelectedItems[0]}

                    searchInputPlaceholderText="Select or Type a value"
                    filterMethod="full"

                    single={true}

                    // Workaround - Change#2: comment the following line 
                    // selectedItems={this.state.demo1_SelectedItems}

                    onSelectedItemsChange={this.demo1_OnSelectedItemsChange}

                    canAddItems={true}
                    onAddItem={this.demo1_OnAddItem}
                />
senzNirojan commented 2 years ago
  1. You can hide the dropdown model by manually toggle the selector to add this command. (by using ref)
    this.yieldRef._toggleSelector();
  2. Then need to push the new items to existing array of items
        const obj = {
            id: value[0],
            name: value[0]
        }
        items.push(obj)
  3. Then set the state to selected item as the current value this.setState({selectedYield: value});

Altogether simple pass this function onSelectedItemsChange

changeYieldText = value => {
        this.yieldRef._toggleSelector();
        const obj = {
            id: value[0],
            name: value[0]
        }
        items.push(obj)
        this.setState({selectedYield: value});
}

But one think to note: this is only for newly added items, for previous existing items in list you don't need to push to the existing array. Otherwise it will duplicated.