2016-03-01 82 views
0

我有一個表格中的數據輸入表格,根據表格中有多少列生成輸入。我努力分離輸入,但是當我改變一個值時,所有的輸入都會改變。有什麼方法可以區分它們,以便我可以在每個輸入中輸入不同的值。我正在使用React和flux。反應 - 區分表格中動態生成的輸入

這裏是我目前正與代碼:

import React from 'react'; 
import AppStore from '../../stores/AppStore'; 

export default class RowForm extends React.Component { 
    state = {input: ''}; 
    onChange = (e) => { 
     this.setState({input: e.target.value}); 
     console.log(input); 
    }; 

    editStop =() => { 
     this.props.editStop(); 
    }; 

    handleSubmit = (e) => { 
     e.preventDefault(); 

     let access_token = AppStore.getToken(); 
     let id = AppStore.getTable().id; 

     this.props.handleSubmit(access_token, id); 

    }; 

    render() { 

     let {input} = this.state; 
     let dataEntries = AppStore.getTable().columns; //this gets the amount of columns so I can map through them and generate the correct amount of inputs. 

     return (
      <tr> 
       {dataEntries.map((element, index) => { 
        return (
         <td key={index}><input type="text" className="form-control" id={element.id} placeholder="enter data" value={this.state.input} onChange={this.onChange} /></td> 
        ); 
       })} 
       <td> 
        <button className="btn btn-default" onClick={this.editStop}><i className="fa fa-ban"></i>Cancel</button> 
        <button className="btn btn-success" onClick={this.handleSubmit}><i className="fa fa-check"></i>Save</button> 
       </td> 
      </tr> 
     ); 
    } 
} 

任何幫助將不勝感激,尤其是例子!

感謝您的時間

回答

1

您可以創建在onChange處理程序的匿名函數:

<input key={index} onChange={event => this.onChange(event, index)}/> 

然而,更大的問題是,你是不是映射你的AppStore.getTable().columns說出任何地方,所以你贏了」根本無法修改組件狀態。此外,您正在使用React不正確地使用ES6類。

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

    this.state = { 
     inputs: {0: null, 1: null, 2: null} 
    }; 
    } 

    onChange (event, index) { 
    this.setState({inputs[index]: event.target.value}); 
    } 
} 

如果您需要映射AppStore.getTable().columns你應該向下傳遞數據作爲道具。將道具映射到狀態是一種反模式。

class App extends React.Component { 
    constructor() { // initialize stuff... } 

    componenDidMount() { 
    this.setState({columns: AppStore.getTable().columns}); 
    } 

    onChange (event, index) { 
    this.setState({columns[index]: event.target.value}); 
    } 

    render() { 
    <RowForm columns={this.state.columns} handleChange={this.onChange}/> 
    } 
} 

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

    render() { 
    <div> 
     {this.props.columns.map(index => { 
     return <input onChange={event => this.props.handleChange(event, index)}/> 
     })} 
    </div> 
    } 
} 

然而,當onChange稱爲該不會更新AppStore。爲此,您需要以某種方式跟蹤全局狀態。我建議查看Redux


更新的答案,試圖與目前的條件下修復代碼:

class RowForm extends React.Component { 
    // Set `dataEntries` to an empty array. This will prevent errors 
    // from appearing in between `render` and `componentDidMount`. 
    // e.g.: `this.state.dataEntries.map` is undefined or not an Array. 
    // You may want to make this a little bit more fail safe though. 
    state = {dataEntries: []}; 

    onChange = (event, element) => { 
     // This assumes `element` is a string based on the column name. 
     this.setState({dataEntries[element]: event.target.value}); 
    } 

    componentDidMount() { 
     // Set state with columns from the table. 
     // Whenever this component mounts it will reset to the state 
     // from `AppStore` unless you set up event listeners like in 
     // Flux or migrate to Redux 

     // This also assumes that `getTable().columns` returns an array 
     // of column names. I don't know what your data structure looks 
     // like so it's hard for me to help here. You need to turn the 
     // array into an object to store values in the keys. 

     let dataEntries = AppStore.getTable().columns.reduce((obj, name) => { 
      obj[name] = null; 
      return obj; 
     }, {}); 
     this.setState({dataEntries}); 
    } 

    render() { 
     let {dataEntries} = this.state; 

     // It is not really recommended to use indexes here because 
     // of the way React diffing works. If `element` is a string 
     // you can use that as the key/index instead. Also, it needs 
     // to be unique within the array. 
     // Turn dataEntries back into an array so map will work properly. 
     return (
      <tr> 
       {Object.keys(dataEntries).map((element) => { 
        return (
         <td key={element}><input type="text" className="form-control" id={element} placeholder="enter data" value={dataEntries[element]} onChange={event => this.onChange(event, element)} /></td> 
        ); 
       })} 
       <td> 
        <button className="btn btn-default" onClick={this.editStop}><i className="fa fa-ban"></i>Cancel</button> 
        <button className="btn btn-success" onClick={this.handleSubmit}><i className="fa fa-check"></i>Save</button> 
       </td> 
      </tr> 
     ); 
    } 
} 
+0

我使用一些ES7 initialisers這就是爲什麼我不使用從ES6構造。不幸的是,我不得不一直建立在流量上,但是我試圖做到這一點,所以我可以開始使用redux。你的回答確實有幫助,但是在onChange事件中,如何將索引映射到列?當我運行我的構建任務時,我得到了一個錯誤?! – BeeNag

+0

我更新了答案,以嘗試和幫助。您需要將AppStore映射到組件本地狀態。我已經向您展示瞭如何使用上述註釋完成此操作。我強烈建議儘可能從本地州遷移。祝你好運! – Mike

+0

感謝您的有用答案Mike!我幾乎可以工作,但是當我嘗試輸入輸入數據時,它從多個輸入變爲單個輸入,你知道爲什麼會發生這種情況嗎? – BeeNag