Search code examples
javascriptreactjsreact-bootstrap-typeahead

Setting the default value in multiselect in react


I use the React bootstrap Typeahead library (https://github.com/ericgio/react-bootstrap-typeahead). My problem is that based on the indexes this.state.todo I need to find objects with given indexes insidethis.state.todos. Display names of found objects as defaults in multiselect.

Demo here: https://stackblitz.com/edit/react-rsfpup

class App extends Component {
  constructor() {
    super();
    this.state = {
      todos: [{id:1, name: 'Paul'}, {id:2, name: 'Martin'}, {id:3, name: 'Jacob'}],
      todo:[1, 3],
      selectedItems: []
    };
  }

  handleSelect = items => {

    this.setState({ selectedItems: items });
  };

  render() {

    return (
      <div>
        <Todos 
          todos={this.state.todos}
          todo={this.state.todo}
          handleSelect = {this.handleSelect}
        />
      </div>
    );
  }
}

class Todos extends Component {
   constructor(props) {
    super(props);

  }

  render() {
    var tempArr = this.props.todos.filter(item => !this.props.todo.includes(item));



    return (
      <div>
        <Typeahead
          id={'example4'}
          labelKey="name"
          multiple
          selected={tempArr}
          options={this.props.todos}
          onChange={this.props.handleSelect}
        />
      </div>
    );
  }
}

Solution

  • I think you are looking for this,

    let selected = this.state.todos.map( (todo, index) => {
       if(this.state.todo.includes(index)){  //compare based on index
          return todo
       }
    })
    

    If you want to compare based on id in this.state.todos,

    let selected = this.state.todos.map( (todo, index) => {
       if(this.state.todo.includes(todo.id)){  //compare based on id in this.state.todos
          return todo
       }
    })
    

    Update

    Based on your demo example, you need to set the selectedItems in your App component only and need to pass the same to your Todos component.

    componentDidMount(){
        //Based on index
        this.setState({
          selectedItems: this.state.todos.filter( (todo, index) => this.state.todo.includes(index))
        })
    
        //Based on id in this.state.todos
        // this.setState({
        //   selectedItems: this.state.todos.filter( (todo, index) => this.state.todo.includes(todo.id))
        // })
    }
    

    Note: Instead of map, you need to use filter here.

    Pass the selectedItems to Todos component,

    <Todos 
        todos={this.state.todos}
        todo={this.state.todo}
        handleSelect = {this.handleSelect}
        selectedItems = {this.state.selectedItems}  //Pass selectedItems here
    />
    

    In Todos component, you need to use selectedItems

    <Typeahead
        id={'example4'}
        labelKey="name"
        multiple
        selected= {this.props.selectedItems}  //Use selectedItems here
        options={this.props.todos}
        onChange={this.props.handleSelect}
    />
    

    Demo