Reactjs与LinkedStateMixin并选择多个选项

时间:2014-06-28 20:51:21

标签: reactjs

使用Reactjs,我希望有一个handleChange方法来处理所有表单元素的修改。

我理解LinkedStateMixin因此而存在,我应该使用

render: function() {
    return <select multiple={{ true }} valueLink={this.linkState('value')}>...options...</select>;
  }

绑定我的select元素的状态。

但似乎这种做事方式不适用于多个选择:state.value已更新但只有一个值(当我选择2个选项时,我可以看到React更新DOM并且它系统地删除了一个选择)。

所以我的问题是:LinkedStateMixin是这个用例的死胡同吗?你如何处理这个选择多用例?

1 个答案:

答案 0 :(得分:3)

根本问题是具有.value属性的select元素的multiple仅返回它包含的第一个选定选项元素的值。因此,当ValueLink mixin调用event.target.value来获取select的新值时,它不会返回所需的数组以使value属性生效。< / p>

您可以围绕select构建一个小包装器以使其工作;这是我的版本(plus a JSFiddle example):

// A select element that supports `multiple` and `valueLink` correctly
var BetterSelect = React.createClass({
  render: function() {
    if (this.props.valueLink) {
      return this.transferPropsTo(
        <select value={this.props.valueLink.value}
                valueLink={null} onChange={this.handleChange}>
          {this.props.children}
        </select>
      );
    } else {
      return this.transferPropsTo(
        <select onChange={this.handleChange}>
          {this.props.children}
        </select>
      );
    }
  },

  handleChange: function(e) {
    var selectedValue;
    if (this.props.multiple) {
      // We have to iterate the `options` elements
      // to figure out which ones are selected.
      selectedValue = [];
      var options = e.target.options;
      for (var i = 0, l = options.length; i < l; i++) {
        if (options[i].selected) {
          selectedValue.push(options[i].value);
        }
      }
    } else {
      selectedValue = e.target.value;
    }

    // Fire onChange manually if it exists since we overwrote it
    this.props.onChange && this.props.onChange(e);

    // Finally, manually take care of any valueLink passed
    if (this.props.valueLink) {
      this.props.valueLink.requestChange(selectedValue);
    }
  }
});


// Let's try it out:
var Application = React.createClass({
  mixins: [React.addons.LinkedStateMixin],

  getInitialState: function() {
    return { value: ['Apples', 'Oranges'] };
  },

  render: function() {
    return (
      <div>
        <pre>{JSON.stringify(this.state.value)}</pre>
        <BetterSelect multiple valueLink={this.linkState('value')}>
          <option value='Apples'>Apples</option>
          <option value='Bananas'>Bananas</option>
          <option value='Oranges'>Oranges</option>
        </BetterSelect>
      </div>
    );
  }
});