2017-06-13 2 views
1

複雑なフォームの編集キーと値のペアに反応しますコンテナコンポーネントは、私は絵を見る、キー/値のペアのオブジェクトを編集するためのフォームを構築してい

items: [{ 
    name: "Product Name", 
    sku: "00001", 
    attributes: { 
     width: "value", 
     height: "value", 
     length: "value", 
     color: "value" 
    } 
}, 
{ 
    name: "Product Name 2", 
    sku: "00002", 
    attributes: { 
     description: "Hello World", 
     weight: "250", 
     quantity: "500", 
     hello: "World" 
    } 
}] 

次に、データを小道具を介して子コンポーネントに渡します。これは、フォームのコードです:今

class EditForm extends Component { 
    render() { 
     let editForm = this.props.items && this.props.items.map((item, idx) => { 
      return(
       <tr key={item.sku}> 
        <td className="edit-table"> 
         <input 
          value={item.name} 
          name={item.name} 
          onChange={(e)=> this.props.onChange(e, idx)} 
         /> 
        </td> 
        <td className="edit-table"> 
         <ul className="item-attributes"> 
          {Object.keys(item.attributes).map((key) => { 
           return (<li key={key}> 
                <label>{key}</label> 
                <input 
                 value={item.attributes[key]} 
                 onChange={(e) => this.props.onChange(e, idx) } 
                /> 
               </li>) 
          })} 
         </ul> 
        </td> 
       </tr> 
      ) 
     }) 

     return(
      <table className="editcontainer-table"> 
       <thead> 
        <tr> 
         <th>SKU</th> 
         <th>Attributes</th> 
        </tr> 
       </thead> 
       <tbody> 
        {editForm} 
       </tbody> 
      </table> 
     ); 
    } 
} 

、これは私がこだわっているところ、私は私が状態のオブジェクトを編集して返送するためのonChange機能がどのように動作するかを把握しようとしているあります更新のためにサーバーに送信します。

+0

あなたがどこかのEditFormコンポーネントのformタグを使用していますか? –

+0

の直前にがあります。 –

+0

フォームの状態はどこに保存していますか?それはEditFormの親ですか? –

答えて

1
  1. 属性は属性ごとに名前を入力与える
  2. 項目名入力にname="name"属性を与える:name={key}

あなたは今onChangeに編集されているものを識別することができます - に基づいて、適切な状態変化を作りますインデックスと入力名が変更されています。

+0

ありがとうございます。ただし、SKUのアイテムが10以上で、各スキューに20以上の属性がある場合、パフォーマンスは非常に遅くなるようです。 –

1

私はになります。ここではアクションでこの解決策を示すサンプルアプリだ

onChange = (e, index) => { 
    let {name, value} = e.target 
    let updateSpec 
    if (name === 'name') { 
     updateSpec = { 
     [index]: { 
      name: {$set: value} 
     } 
     } 
    } 
    else { 
     updateSpec = { 
     [index]: { 
      attributes: { 
      [name]: {$set: value} 
      } 
     } 
     } 
    } 
    this.setState({items: update(this.state.items, updateSpec)}) 
    } 

:(import update from 'immutability-helper'を使用して)onChangeは次のようになります。を変更するあなたのコンテナ内機能は次のようにします

onChange = (e, sku, field) => { 
 
    const updatedItems = this.state.items.map(e => { 
 
    if (e.sku !== sku) return e; 
 
    if (field === 'name') { 
 
     e.name = e.target.value; 
 
    } else { 
 
     // has to be attributes 
 
     e.attributes[field] = e.target.value; 
 
    } 
 
    return e; 
 
    }); 
 
    this.setState({ 
 
    items: updatedItems, 
 
    }) 
 
}

追加SKUパラメータはアイテムアレイと、変更したいフィールド内の項目を識別するために。 skuは変更されないため、これをアイテム識別子として使用できます。これにより、製品名とその属性を変更することができます。完全な作業コードについては、以下のコード例を参照してください。

class Container extends React.Component { 
 
    constructor() { 
 
    super(); 
 
    this.state = { 
 
     items: [{ 
 
     name: "Product Name", 
 
     sku: "00001", 
 
     attributes: { 
 
      width: "value", 
 
      height: "value", 
 
      length: "value", 
 
      color: "value" 
 
     } 
 
     }, 
 
     { 
 
     name: "Product Name 2", 
 
     sku: "00002", 
 
     attributes: { 
 
      description: "Hello World", 
 
      weight: "250", 
 
      quantity: "500", 
 
      hello: "World" 
 
     } 
 
     }], 
 
    } 
 
    } 
 
    
 
    onChange = (e, sku, field) => { 
 
    console.log(e.target.value); 
 
    const updatedItems = this.state.items.map(item => { 
 
     if (item.sku !== sku) return item; 
 
     if (field === 'name') { 
 
     item.name = e.target.value; 
 
     } else { 
 
     // has to be attributes 
 
     item.attributes[field] = e.target.value; 
 
     } 
 
     return item; 
 
    }); 
 
    this.setState({ 
 
     items: updatedItems, 
 
    }) 
 
    } 
 
    
 
    render() { 
 
    // log new state here 
 
    console.log(this.state.items); 
 
    return <EditForm onChange={this.onChange} items={this.state.items} /> 
 
    } 
 
    
 
} 
 

 
class EditForm extends React.Component { 
 
    render() { 
 
    let editForm = this.props.items && this.props.items.map((item, idx) => { 
 
     return(
 
     <tr key={item.sku}> 
 
      <td className="edit-table"> 
 
      <input 
 
       value={item.name} 
 
       name={item.name} 
 
       onChange={(e)=> this.props.onChange(e, item.sku, 'name')} 
 
      /> 
 
      </td> 
 
      <td className="edit-table"> 
 
      <ul className="item-attributes"> 
 
       {Object.keys(item.attributes).map((key) => { 
 
        return (<li key={key}> 
 
             <label>{key}</label> 
 
             <input 
 
              value={item.attributes[key]} 
 
              onChange={(e) => this.props.onChange(e, item.sku, key) } 
 
             /> 
 
            </li>) 
 
       })} 
 
      </ul> 
 
      </td> 
 
     </tr> 
 
    ) 
 
    }) 
 

 
    return(
 
     <table className="editcontainer-table"> 
 
     <thead> 
 
      <tr> 
 
      <th>SKU</th> 
 
      <th>Attributes</th> 
 
      </tr> 
 
     </thead> 
 
     <tbody> 
 
      {editForm} 
 
     </tbody> 
 
     </table> 
 
    ); 
 
    } 
 
} 
 

 
ReactDOM.render(<Container />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> 
 
<div id="app"></div>

+0

ありがとう、私は別の問題があります。 onChange関数では、 'this'の値はsetStateまたは状態を持ちません。もし私がコンソールであれば。log(this) 'this'の値は親コンテナからEditFormコンポーネントに渡す小道です –

+0

本当ですか?私は内部でそれを使用しているので、これはsetStateとstateを持つ必要があります。あなたがどこにログを記録し、出力を表示することができますか? –

+0

実際に 'this.handleChange = this.handleChange.bind(this)'を親コンポーネントコンストラクタに追加すると、問題が解決しました –

関連する問題