Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
136
rated 0 times [  139] [ 3]  / answers: 1 / hits: 48483  / 9 Years ago, wed, december 16, 2015, 12:00:00

I have an array of emails (as a part of a bigger model). These are displayed in seperate rows witha remove button for each (the address itself can be updated in the input box directly). Unfortunately I dont know how to do this in react when the inputs are renderd using a map function.
(I am converting a meteor blaze project to meteor react).



Everything renders but how do I attach to change event so I can update my array of emails? onChange + value need to be set somehow.



This is the map function



return this.data.emailGroup.emails.map((email) => {
return (
<div key={email} className=input-group>
<input type=text className=form-control onChange={self.handleEmailListChange} value={email}/>

<div className=input-group-btn>
<button type=button
className=btn btn-default remove-email><span
className=glyphicon glyphicon-remove></span></button>
</div>
</div>
);
});


The initial state(which is populated with data from the db:



 getInitialState() {
return {
name : '',
description: '',
emails : [],
newEmailAddress : ''
}
},


Upon request here is the render method(it requires a getContent method.The getcontent method is there because in meteor I need to wait for data so in the meantime I need a loading state.



   getContent() {
return (

<div className=box box-success>
<div className=box-header with-border>
<h3 className=box-title>List of emails</h3>
</div>
<form role=form className=form-horizontal>
<div className=box-body>
<p>Below is a list of email addresses which are added to this email group. If
you
want
to add more
you can add them one by one by inputting in the box below or add a list into
the
same box (email
addresses have to be seperated by either a space or ;) then press Add to add
to
the
list. You can edit
the addresses directly as well as remove them.</p>
<div className=input-group>
<input type=text className=form-control

value={this.state.newEmailAddress}
onChange={this.handleAddNewEmail}
placeholder=Email addresses seperated by a space or a semicolon ; i.e. [email protected];[email protected]/>
<span className=input-group-btn>
<button type=button onClick={this.handleAddNewEmailButton} className=btn btn-info btn-flat add-email>Add</button>
</span>
</div>
<br/>
{this.renderEmail()}
</div>
</form>
</div>
)
},
render()
{
var contentStyle = {
minHeight : '946px'
};
return (
<div className=content-wrapper style={contentStyle}>
<section className=content-header>
<h1>
{this.data.emailGroup? this.data.emailGroup.name : 'hello'}
</h1>
<small> Created by: Christian Klinton</small>
<br/>
<small> Last updated by: Christian Klinton - 2015-11-12 08:10:11</small>
<ol className=breadcrumb>
<li><a href=/emailGroups><i className=fa fa-dashboard></i> Home</a></li>
<li><a href=/emailGroups>Email groups</a></li>
<li className=active>{this.data.emailGroup? this.data.emailGroup.name : 'loading'}</li>
</ol>
</section>
<section className=content>
<div className=row>
<div className=col-md-6>
<div className=box box-primary>
<div className=box-header with-border>
<h3 className=box-title>Information</h3>

</div>
<form role=form>
<div className=box-body>
<div className=form-group>
<label htmlFor=inputName>Name</label>
<input type=email className=form-control id=name
onChange={this.handleNameChange}
placeholder=Set the name of the email group autoComplete=off
value={this.state.name}/>
</div>

<div className=form-group>
<label>Description</label>
<textarea className=form-control rows=3 id=description
placeholder=Enter a description what and how the template is used...
onChange={this.handleDesriptionChange}
value={this.state.description}
></textarea>
</div>


</div>
</form>
</div>
</div>
<div className=col-md-6>
{this.data.emailGroup? this.getContent() : <p>Loading</p> }
</div>
<div className=form-group>
<div className=col-sm-offset-8 col-sm-4>
<div className=pull-right>
<button className=btn btn-primary>Delete all</button>
<button className=btn btn-primary save>Save</button>
</div>
</div>
</div>
</div>
</section>
</div>
)
}

More From » meteor

 Answers
47

React requires you to have something unique for every element in the rendered array, it's called a key, and it's an attribute.



If you don't know what to assign to the key, just assign it the array's indexes:



this.props.doors.map((door, index) => (
<div key={index} className=door></div>
));


Here's the same solution applied to your problem:



return this.data.emailGroup.emails.map((email, index) => {
return (
<div key={index} className=input-group>
<input type=text
className=form-control
onChange={self.handleEmailListChange.bind(this, index)} value={email}/>
</div>
);
});


Notice how I bound handleEmailListChange to receive the index of the modified email. If handleEmailListChange accepts an index, it can update the modified email within the state:



handleEmailListChange: function(index, event) {
var emails = this.state.emails.slice(); // Make a copy of the emails first.
emails[index] = event.target.value; // Update it with the modified email.
this.setState({emails: emails}); // Update the state.
}

[#64040] Monday, December 14, 2015, 9 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
luna

Total Points: 698
Total Questions: 114
Total Answers: 93

Location: Israel
Member since Wed, Apr 14, 2021
3 Years ago
luna questions
;