0
votes

I am trying to use redux-form with react-widget Multiselect this example:

var Multiselect = ReactWidgets.Multiselect
  , people = listOfPeople();

var Example = React.createClass({

  getInitialState() {
    return { value: people.slice(0,2) };
  },

  _create(name){
    var tag = { name, id: people.length + 1 }
    var value = this.state.value.concat(tag)
    // add new tag to the data list
    people.push(tag)
    //add new tag to the list of values
    this.setState({ value })
  },

  render(){
    // create a tag object
    return (
      <Multiselect data={people}
        value={this.state.value}
        textField="name"
        onCreate={this._create}
        onChange={value => this.setState({ value })}/>
    )
  }
});

ReactDOM.render(<Example/>, mountNode);

Below is a code snippet for a parent component which makes usage of redux-form (EditVideo component) component (please look at the comments in onSubmit method):

class VideoEdit extends React.Component {
  constructor(props) {
    super(props);
  }

  onSubmit = (values) => {

    console.log(values.categories) // always returns initialValues for categories, new values not adding

  }

  render() {
    const { loading, videoEdit, categories } = this.props;    

    if (loading) {
      return (
        <div>{ /* loading... */}</div>
      );
    } else {
      return (
        <div>          
          <h2>Edit: {videoEdit.title}</h2>
          <EditVideo
            onSubmit={this.onSubmit}
            initialValues={videoEdit} 
            categories={categories}
          />
        </div>
      );
    }
  }
}

And here is a code snippet of redux-form component with react-widget Multiselect component:

class CategoryWidget extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      value: this.props.defValue,
      extData: this.props.data
    }

    this._create = this._create.bind(this);
  }

  _create(name) {
    var tag = { name, id: this.state.extData.length + 100 + 1 }

    var value = this.state.value.concat(tag)
    var extData = this.state.extData.concat(tag)

    this.setState({
      extData,
      value
    })
  }

  render() {
    return (
      <Multiselect
        {...this.props.input}
        data={this.state.extData}
        onBlur={() => this.props.input.onBlur()}
        value={this.state.value || []}
        valueField="id"
        textField="name"
        onCreate={this._create}
        onChange={value => this.setState({ value })}
      />
    )
  }
}

const EditVideoForm = (props) => {

  const { handleSubmit, submitting, onSubmit, categories, initialValues, defBook } = props;

  return (
    <Form name="ytvideo" onSubmit={handleSubmit(onSubmit)}>      
      <div>
        <Field
          name="categories"
          component={CategoryWidget}
          data={categories}
          defValue={initialValues.categories}
        />
      </div>
      <br />
      <Button color="primary" type="submit" disabled={submitting}>
        Submit
      </Button>
    </Form>
  );
};

export default reduxForm({
  form: 'videoEdit',
  enableReinitialize: true
})(EditVideoForm);

The Multiselect widget works as expected, yet the form on submit always returns the same initial values for categories.

I believe the problem lays in the fact that CategoryWidget is a class base component? If so, what is a way to make it work?

1

1 Answers

0
votes

Here is what I have done for my Multiselect at the end:

class CategoryWidget extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      value: this.props.defValue,
      extData: this.props.data
    }

    this._create = this._create.bind(this);
  }

  _create(name) {
    var tag = { name, id: this.state.extData.length + 100 + 1 }

    var value = this.state.value.concat(tag)
    var extData = this.state.extData.concat(tag)

    this.setState({
      extData,
      value
    })
  }

  componentDidUpdate() {
    let { onChange } = this.props.input
    onChange(this.state.value)
  }

  handleOnChange(value) {
    this.setState({ value })
  }

  render() {
    const input = this.props.input
    return (
      <Multiselect
        {...input}
        data={this.state.extData}
        onBlur={() => input.onBlur()}
        value={this.state.value || []}
        valueField="id"
        textField="name"
        onCreate={this._create}
        onChange={value => this.handleOnChange(value)}
      />
    )
  }
}