动态添加/删除表单输入块

时间:2020-01-22 16:40:39

标签: javascript arrays reactjs

当我单击加号按钮时,我想重复同一行字段。我尝试根据状态属性 plus 来实现此功能,当我单击按钮时,状态属性更改为true,然后检查此状态属性是否为true?添加字段:null。但这不起作用,我想我缺少一些概念,请帮忙!

组件状态:

  this.state = {
            plus : false 
        }

plusHandler:

plus = (e)=>{
    this.setState({
        plus: true,
     });
    }

在渲染中:

     <div className="form-row">
                <div className="form-group col-md-5">
                    <label htmlFor="cRelation">Relation</label>
                    <select name="cRelation" defaultValue={''} id="cRelation" className="form-control">
                        <option disabled value=''> select relation</option>
                        {relationList.map(item => (
                            <option key={item} value={item}>{item}</option>
                         )
                        )}
                    </select>
                </div>
                <div className="form-group col-md-6">
                    <label htmlFor="withConcept">withConcept</label>
                    <select name="withConcept" defaultValue={''} id="withConcept" className="form-control">
                        <option value='' disabled> select concept</option>
                        {(conceptList|| []).map(item => (
                        <option key={item.conceptId} value={item.conceptId}>{item.conceptName}</option>
                    ))}

                    </select>

                </div>
                <div className="form=group align-self-sm-center mt-2">
                    <button type="button" className="btn btn-sm btn-outline-success m-2" onClick={this.plus}>+</button>
                    <button type="button" className="btn btn-sm btn-outline-danger pr-2">-</button>
                </div>
            </div>

{this.state.plus? 
                <div className="form-row">
                <div className="form-group col-md-5">
                    <label htmlFor="cRelation">Relation</label>
                    <select name="cRelation" defaultValue={''} id="cRelation" className="form-control">
                        <option disabled value=''> select relation</option>
                        {relationList.map(item => (
                            <option key={item} value={item}>{item}</option>
                         )
                        )}
                    </select>
                </div>
                <div className="form-group col-md-6">
                    <label htmlFor="withConcept">withConcept</label>
                    <select name="withConcept" defaultValue={''} id="withConcept" className="form-control">
                        <option value='' disabled> select concept</option>
                        {(conceptList|| []).map(item => (
                        <option key={item.conceptId} value={item.conceptId}>{item.conceptName}</option>
                    ))}

                    </select>

                </div>
                <div className="form=group align-self-sm-center mt-2">
                    <button type="button" className="btn btn-sm btn-outline-success m-2"  onClick={this.plus}>+</button>
                    <button type="button" className="btn btn-sm btn-outline-danger pr-2">-</button>
                </div>
            </div>
    :null }

这是我想要的输出:

enter image description here

3 个答案:

答案 0 :(得分:1)

我认为它不是添加/删除输入字段,而是管理表单状态以保持必要的元素可见性。

只要您要访问在那些输入字段中选择的值(例如,在提交表单时),而不是使用布尔标志,就可能需要在状态内将动态表单行存储为以下结构的数组:< / p>

[
   {rowId:..., selectedOptions:{relation:..., concept...}},
   ...
]

为简便起见,我还将动态表格行重新设计为一个单独的组件。

这样,我会将行组件中添加/删除按钮的onClick()事件处理程序附加到父窗体组件的回调中,该父处理程序将在其状态内追加/删除数组项,从而使相应的行组件出现/消失。

您可以在下面的实时片段中查询该概念的完整说明:

const { useState } = React,
      { render } = ReactDOM
      
const relations = ['relation1', 'relation2', 'relation3'],
      concepts = ['concept1', 'concept2', 'concept3']

const FormRow = ({rowId, selectedOptions, onSelect, onAdd, onRemove}) => {
  const handleChange = e => onSelect(rowId, e.target.getAttribute('param'), e.target.value)
  return (
    <div>
      <label>Relation:
        <select param="relation" onChange={handleChange} value={selectedOptions.relation||''}>
          <option value="" disabled>select relation</option>
          {
            relations.map((rel,key) => <option {...{key}} value={rel}>{rel}</option>)
          }
        </select>
      </label>
      <label>With Concept:        
        <select param="concept" onChange={handleChange} value={selectedOptions.concept||''}>
          <option value="" disabled>select concept</option>
          {
            concepts.map((con,key) => <option {...{key}} value={con}>{con}</option>)
          }
        </select>
      </label>
      <button type="button" onClick={onAdd}>+</button>
      <button type="button" onClick={() => onRemove(rowId)}>-</button>
    </div>
  )
}

const Form = () => {
  const [rows, setRows] = useState([{rowId:0, selectedOptions:{}}]),
        onAddRow = () => {
          const maxRowId = Math.max(...rows.map(({rowId}) => rowId))
          setRows([...rows, {rowId: maxRowId+1, selectedOptions:{}}])
        },
        onRemoveRow = id => setRows(rows.filter(({rowId}) => rowId != id)),
        onSelectRow = (id, param, val) => {        
          const rowsCopy = [...rows],
                item = rowsCopy.find(({rowId}) => rowId == id)
                Object.assign(item, {selectedOptions:{...item.selectedOptions, [param]:val}})
          setRows(rowsCopy)
        }
  return (
    <form onSubmit={e => (e.preventDefault(), console.log(rows))}>
      {
        rows.map(({rowId, selectedOptions}, key) => (
          <FormRow 
            {...{key, rowId, selectedOptions}}
            onAdd={onAddRow}
            onRemove={onRemoveRow}
            onSelect={onSelectRow}
          />
        ))
      }
    <input type="submit" value="Submit" />
    </form>
  )
}

render (
  <Form />,
  document.getElementById('root')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script><div id="root"></div>

答案 1 :(得分:0)

您需要一个包含要渲染项目的列表。当用户单击加号按钮时,您需要添加一个新元素。

示例:

ConnectionFactory

答案 2 :(得分:0)

代替整数,使用整数来表示行数,如下所示。加处理程序将增加计数。

this.state = {
                i: 1
            }

Plus处理程序

plus = (e) => {
            this.setState({
                i: this.state.i + 1
            });
        }

渲染功能:

 rowfunction() {
        return (<div className="form-row">
            <div className="form-group col-md-5">
                <label htmlFor="cRelation">Relation</label>
                <select name="cRelation" defaultValue={''} id="cRelation" className="form-control">
                    <option disabled value=''> select relation</option>

                </select>
            </div>
            <div className="form-group col-md-6">
                <label htmlFor="withConcept">withConcept</label>
                <select name="withConcept" defaultValue={''} id="withConcept" className="form-control">
                    <option value='' disabled> select concept</option>


                </select>

            </div>
            <div className="form=group align-self-sm-center mt-2">
                <button type="button" className="btn btn-sm btn-outline-success m-2 " onClick={this.plus}>+</button>
                <button type="button" className="btn btn-sm btn-outline-danger pr-2">-</button>
            </div>
        </div>)
    }
    render() {
        var rows = [];
        for (let index = 0; index < this.state.i; index++) {
            rows.push(this.rowfunction())
        }
        return rows;

    }