2016-09-29 2 views
2

Я построил Реагировать таблицу следующим образом:Реагировать редактируемую таблицу

const Table = ({data}) => { 

    return (
     <table className="table table-bordered"> 
      <thead> 
       <tr> 
        <th>Qty</th> 
        <th>Description</th> 
        <th>Price (£)</th> 
       </tr> 
      </thead> 
      <tbody> 
       {data.map((row) => { 
        return (
         <tr> 
          <td><input type='number' className='form-control' step='1' min="1" value={row[0]}/></td> 
          <td><input type='text' className='form-control' value={row[1]}/></td> 
          <td><input type='text' className='form-control' placeholder='6.00' value={row[2]}/></td> 
         </tr> 
        ); 
       })} 
      </tbody> 
     </table> 
    ); 
}; 

Table.propTypes = { 
    data: React.PropTypes.array.isRequired 
}; 

export default Table; 

В классе я использую этот компонент, я передаю данные в качестве параметра (который изначально пуст):

materials: [[],[],[],[],[],[],[],[],[],[]] //Initialise with 10 empty rows 


<Table data={materials} /> 

Это создаст таблицу с 10 пустыми строками. Единственная проблема в том, что когда я ввожу данные в таблицу, массив данных, который я сопоставил, не обновляет данные, которые я ввел.

Table with data entered

Я думаю, что мне нужно какое-то событие, где я могу обновить данные с снимкой, что было введено, но я не уверен, как это реализовать. Любая помощь будет принята с благодарностью.

ответ

3

Реакция не работает с двусторонней привязкой данных, например, с угловым JS. props доступны только для чтения, поэтому вам нужно обновить их, где они принадлежат.

Например, компонент Parente, где <Table /> объявлен может иметь materials массив в своем состоянии и, кроме того, проходя materials в качестве реквизита, он может передать обработчик функции как onCellChange(row, column), так что вы можете связать его с onChange событий в вводит элементы.

Как так,

const Table = ({data, onCellChange}) => { 

return (
    <table className="table table-bordered"> 
     <thead> 
      <tr> 
       <th>Qty</th> 
       <th>Description</th> 
       <th>Price (£)</th> 
      </tr> 
     </thead> 
     <tbody> 
      {data.map((row, index) => { 
       return (
        <tr key={index}> 
         <td><input type='number' className='form-control' step='1' min="1" value={row[0]} onChange={() => onCellChange(index, 0)}/></td> 
         <td><input type='text' className='form-control' value={row[1]} onChange={() => onCellChange(index, 1)}/></td> 
         <td><input type='text' className='form-control' placeholder='6.00' value={row[2]} onChange={() => onCellChange(index, 2)}/></td> 
        </tr> 
       ); 
      })} 
     </tbody> 
    </table> 
); 
}; 

Table.propTypes = { 
    data: React.PropTypes.array.isRequired 
}; 

Таким образом, в качестве родительского компонента, вы бы объявить компонент как <Table data={this.state.materials} onCellChange={this.onCellChange} />.

И это будет иметь метод, как это:

onCellChange: function(row, column) { 
    //update the cell with this.setState() method 
} 
+0

Эй @Diego. Спасибо за удивительное решение. Это определенно направление, в котором я должен идти. Единственное, что я не вижу, это то, как я могу фактически получить данные, которые были введены из моего обратного вызова в родительском компоненте. Скажи мне, есть ли что-то, чего я здесь не вижу. Спасибо – Granttastic

+0

Извините, я забыл поставить это в примере. Вы должны изменить объявление onChange на нечто вроде 'onChange = {(e) => onCellChange (index, 0, e.target.value}", а также добавить последний параметр в методе, чтобы получить значение от ввода. Я думаю, что он должен работать. –

+0

Это трюк. Спасибо за ваше время! – Granttastic

0

вам необходимо обновить состояние OnChange:

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

Вы можете добиться этого путем поддержания состояния ваших данных таблицы. Я сделал приблизительную структуру, как вы могли бы это сделать здесь: http://codepen.io/PiotrBerebecki/pen/QKrqPO

Посмотрите на вывод консоли, на котором отображаются обновления состояния.

class Table extends React.Component { 
    constructor(props) { 
    super(props); 
    this.state = { 
     materials: props.data 
    }; 
    } 

    handleChange(index, dataType, value) { 
    const newState = this.state.materials.map((item, i) => { 
     if (i == index) { 
     return {...item, [dataType]: value}; 
     } 
     return item; 
    }); 

    this.setState({ 
     materials: newState 
    }); 
    } 

    render() { 
    console.clear(); 
    console.log(JSON.stringify(this.state.materials)); 
    return (
     <table className="table table-bordered"> 
      <thead> 
       <tr> 
        <th>Qty</th> 
        <th>Description</th> 
        <th>Price (£)</th> 
       </tr> 
      </thead> 
      <tbody> 
       {this.state.materials.map((row, index) => { 
        return (
         <tr> 
          <td> 
           <input onChange={(e) => this.handleChange(index, 'qty', e.target.value)} 
            type='number' 
            className='form-control' 
            step='1' min="1" 
            value={this.state.materials[index].qty}/> 
          </td> 
          <td> 
           <input onChange={(e) => this.handleChange(index, 'desc', e.target.value)} 
            type='text' 
            className='form-control' 
            value={this.state.materials[index].desc}/> 
          </td> 
          <td> 
           <input onChange={(e) => this.handleChange(index, 'price', e.target.value)} 
            type='text' 
            className='form-control' 
            placeholder='6.00' 
            value={this.state.materials[index].price}/> 
          </td> 
         </tr> 
        ); 
       })} 
      </tbody> 
     </table> 
    ); 
    } 
} 


const materials = [ 
    { qty: '', desc: '', price: '' }, 
    { qty: '', desc: '', price: '' }, 
    { qty: '', desc: '', price: '' }, 
    { qty: '', desc: '', price: '' }, 
    { qty: '', desc: '', price: '' }, 
    { qty: '', desc: '', price: '' }, 
    { qty: '', desc: '', price: '' }, 
    { qty: '', desc: '', price: '' } 
] 


ReactDOM.render(<Table data={materials} />, document.getElementById('app')); 
+0

Я обновил мой codepen, чтобы продемонстрировать, как вы могли бы сделать это. –

Смежные вопросы