monkeyjumps
monkeyjumps

Reputation: 712

Using ReactJs, How do I update my form fields when my parent object sent in from props changes?

I am using REactJs to dynamically create some form fields. these form fields are mapped to a document object. Visually it is a three column app. A document queue displayed on left with many clickable document icons , fields in the middle and the document image on the right. There can be multiple documents. Each document has fields associated to it. If a user inputs values into the fields then clicks another document. I want the input fields to be reset for the new document or saved values loaded.

Below is the last attempt i tried where I am using the DefaultValue attribute; i've tried to pass the values in from a function. I ve also tried value attribute but that locks the value not allowing the user to change it.

Currently I successfully save the state of the document queue and its fields but i just cannot get the UI to reflect my state object: documentQueue.

I ve read where people suggest using value={state} but that doesn't quite work for my state object. My forms are more dynamic and complex.

var Fields = React.createClass({
getInitialState: function () {
    return {                        
        currentDocumentIndex: 0,
        shouldUpdate: false,
        randomKey : 0
    };
},
componentWillReceiveProps: function (nextProps) {        
    console.log("compare props");
    console.log(nextProps.fields === this.props.fields);
    var forceRender = !(nextProps.fields === this.props.fields);
    //only change state if needed.
    if (forceRender) {
        if (!this.state.shouldUpdate) {
            this.setState({ shouldUpdate: true ,randomKey : Math.random() }, function () {
                console.log("should update fields state set");
                console.log(this.state.shouldUpdate);
            });
        }
    } else {
        if (this.state.shouldUpdate) {
            this.setState({ shouldUpdate: false , randomKey: Math.random() }, function () {
                console.log("should update fields state set");
                console.log(this.state.shouldUpdate);
            });
        }
    }
},
getDataType: function (datatype, fieldId) {        
    switch (datatype) {
        case 0:
        case 1:
        case 2:
        case 3:
        case 4:
            return <div class="col-sm-6"><input type="text" key={this.state.randomKey+1} className="form-control" id={fieldId} onChange={this.onValueChanged.bind(this)} value={this.props.fields[fieldId]}  /></div>
        case 5:
            return <div class="col-sm-6"><input type="text" key={this.state.randomKey+2} className="form-control" id={fieldId}  onChange={this.onValueChanged.bind(this)}  /></div>
        case 6:
            return <div class="col-sm-6"><input type="checkbox" key={this.state.randomKey+3} className="form-control" id={fieldId} value="true" onChange={this.onChecked.bind(this)} /></div>
        case 7:
            return <div class="col-sm-6"><textarea type="text" rows="5" key={this.state.randomKey+4} className="form-control" id={fieldId} onChange={this.onValueChanged.bind(this)}  ></textarea></div>
    }
},    
onChecked : function(event){        
},
onValueChanged : function(event){   
    this.props.onFieldChange(this.props.currentDocumentIndex, event.target.id, event.target.value);                
},
renderFields: function () {
    var fieldNames = [];        
    if (this.props.doctype == null) {
        console.log("fields are null");            
    } else {
        console.log("fields are valid from Field component");            
        for (var index = 0; index < this.props.doctype.Fields.length; index++)
        {                
            var inputField = this.getDataType(this.props.doctype.Fields[index].DataType, this.props.doctype.Fields[index].DocumentTypeFieldID);                
            fieldNames.push(<label className="control-label col-sm-6">{this.props.doctype.Fields[index].Name}</label>);                
            fieldNames.push(inputField);
        }
    }               
    return (            
            <form className="form-horizontal" role="form">
                <div className="form-group">
                    {fieldNames}
                </div>
            </form>            
    );        
},
render: function () {
    return (
        <div>
            {this.renderFields()}
        </div>
        );             
}

});

Upvotes: 0

Views: 2013

Answers (1)

Ben Mosher
Ben Mosher

Reputation: 13381

If you want to manage an input value with React, you can use the value prop.

However, as you've seen, the user can no longer directly edit the field.

To allow user edits, you must also set onChange on the field and write the incoming edits somewhere such as state.

The docs for ReactLink have a good example of this:

var NoLink = React.createClass({
  getInitialState: function() {
    return {message: 'Hello!'};
  },
  handleChange: function(event) {
    this.setState({message: event.target.value});
  },
  render: function() {
    var message = this.state.message;
    return <input type="text" value={message} onChange={this.handleChange} />;
  }
});

Also, you may just want to use ReactLink.

Upvotes: 3

Related Questions