私は(より大きなモデルの一部として)一連のメールを持っています。これらは個別の行に表示され、それぞれに[削除]ボタンが付いています(住所自体は、入力ボックスで直接更新できます)。残念ながら、マップ関数を使用して入力がレンダリングされたときに、これをどのように行うかわかりません。 (私は流星炎プロジェクトを流星反応に変換しています)。
すべてが表示されますが、変更イベントにアタッチして、メールの配列を更新できるようにするにはどうすればよいですか?onChange +値を何らかの方法で設定する必要があります。
これはマップ関数です
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>
);
});
初期状態(dbからのデータが入力されます:
getInitialState() {
return {
name : '',
description: '',
emails : [],
newEmailAddress : ''
}
},
リクエストに応じて、ここにrenderメソッドがあります(getContentメソッドが必要です。流星ではデータを待機する必要があるため、その間はロード状態が必要なので、getcontentメソッドがあります。
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>
)
}
Reactでは、レンダリングされた配列のすべての要素に固有のものが必要です。これはkey
と呼ばれ、属性です。
キーに何を割り当てるかわからない場合は、配列のインデックスを割り当てます。
this.props.doors.map((door, index) => (
<div key={index} className="door"></div>
));
これはあなたの問題に適用された同じ解決策です:
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>
);
});
変更された電子メールのインデックスを受け取るためにhandleEmailListChange
をバインドしたことに注意してください。 handleEmailListChange
がインデックスを受け入れると、変更された電子メールを状態内で更新できます。
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.
}
render()
関数内にArray.map
を直接配置する必要があります。各配列要素が親要素(ここでは<div>
)内にラップされ、一意のkey={}
が必要であることに注意してください
class ArrayMap extends React.Component{
//your functions
handleEmailChanged(key){
// Handle email
}
render(){
return(
<div>
{
this.data.emailGroup.emails.map((email) => {
<div key={email.key}>
<button onClick={this.handleEmailChanged.bind(this,email.key)}/>
</div>
});
}
</div>
);
}
}
あなたが探しているのは次のようなものだと思います:
MyPage = React.createClass({
mixins: [ReactMeteorData],
getMeteorData() {
// ...
},
render() {
const emails = this.data.emailGroup.emails.map((email) => {
return (
<div key={email} className="input-group">
<input type="text" className="form-control"
onChange={this.handleEmailListChange} value={email} />
<div className="input-group-btn">
<button type="button"
className="btn btn-default remove-email"><span
className="glyphicon glyphicon-remove" /></button>
</div>
</div>
);
});
return <div>
{emails}
</div>
}
});
self
をthis
に変更しました。 ES6の矢印関数を使用しているため、self = this
を割り当てる必要はありません。