2

I'm building a component which displays a series of generic input fields. The backing store uses a simple array of key-value pairs to manage the data:

[
{fieldkey: 'Signs and Symptoms', value:'fever, rash'},
{fieldkey: 'NotFeelingWell', value:'false'},
{fieldkey: 'ReAdmission', value:'true'},
{fieldkey: 'DateOfEvent', value:'12/31/1999'}
]

In order to eliminate a lot of boilerplate code related to data binding, the component uses these same keys when generating the HTML markup (see 'data-fieldname' attribute).

var Fields = React.createClass({

handleOnChange:function(e){

    Actions.updateField( {key:e.target.attributes['data-fieldname'].value, value:e.target.value})
},
setValue:function(){
    var ref = //get a reference to the DOM element that triggered this call
    ref.value = this.props.form.fields[ref.attributes['data-fieldname']]
},

render:function(){


 return (<div className="row">
  <Input  data-fieldname="Signs and Symptoms" type="text" label='Notes' defaultValue="Enter text" onChange={this.handleOnChange} value={this.setValue()} />
  <Input  data-fieldname="NotFeelingWell"  type="checkbox" label="Not Feeling Well" onChange={this.handleOnChange} value={this.setValue()}  />
  <Input  data-fieldname="ReAdmission"  type="checkbox" label="Not Feeling Great" onChange={this.handleOnChange} value={this.setValue()} />
  <Input  data-fieldname="DateOfEvent"  type="text" label="Date Of Event"  onChange={this.handleOnChange} value={this.setValue()} />

</div>)
}

})

My goal is to use the same two functions for writing/reading from the store for all inputs and without code duplication (i.e. I don't want to add a refs declaration to each input that duplicates the key already stored in 'data-fieldname') Things work swimmingly on the callback attached to the 'onChange' event. However, I'm unsure how to get a reference to the DOM node in question in the setValue function.

Thanks in advance

3
  • At the moment this.setValue() is executed, the component/element that is associated with that call doesn't even exist yet. Commented Apr 16, 2015 at 18:20
  • Point well taken. Can you suggest an alternative approach that avoids key duplication? Commented Apr 16, 2015 at 18:37
  • 1
    Store the information as an array of objects (for example) and generate the elements dynamically? Commented Apr 16, 2015 at 18:53

2 Answers 2

1

I'm not sure if I understand your question right, but to reduce boilerplate I would map your array to generate input fields:

 render:function(){
 var inputs = [];
 this.props.form.fields.map(function(elem){
     inputs.push(<Input  data-fieldname={elem.fieldkey}  type="text" label="Date Of Event"  onChange={this.handleOnChange} value={elem.value} />);
 });

 return (<div className="row">
  {inputs}

</div>)
}

This will always display your data in props. So when handleOnChange gets triggered the component will rerender with the new value. In my opinion this way is better than accessing a DOM node directly.

Sign up to request clarification or add additional context in comments.

1 Comment

Great and thank you! Such a simple and obvious solution, embarrassed I didn't see it.
0

If you want to use dynamic information on the input, you need to pass it through the array, and make a loop.

Here is a little example based on Dustin code:

var fieldArray = [ //replace by this.props.form.fields
    {
        fieldkey: 'Signs and Symptoms', 
        value: 'fever, rash', 
        type: 'text', 
        label: 'Notes'
    },
    {
        fieldkey: 'NotFeelingWell', 
        value: 'false',
        type: 'checkbox', 
        label: 'Not Feeling Well'
    },
];

var Fields = React.createClass({

    handleOnChange:function(e){
        var fieldKey = e.target.attributes['data-fieldname'].value;

        Actions.updateField({
            key: fieldKey, 
            value: e.target.value
        })
    },

    render() {
        var inputs = [];

        fieldArray.map(function(field) { //replace by this.props.form.fields
            inputs.push(
                <Input
                data-fieldname={field.fieldkey} 
                value={field.value}
                type={field.type} 
                label={field.label}
                onChange={this.handleOnChange} />
            );
        }.bind(this));

        return (
            <div className="row">
                {inputs}
            </div>
        );
    }

});

1 Comment

Awarded Dustin the answer as he was first, but I upvoted yours.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.