web-dev-qa-db-fra.com

Comment implémenter une fiche dynamique avec des composants contrôlés dans React.JS?

Comme je regarde les exemples dans la référence pour controlled form componentssur le site officiel de react.js , je me demande comment on est supposé implémenter une form dans laquelle vous seriez capable de remove et addinput éléments de manière dynamique dans un tel manière qu'ils soient des composants contrôlés? Est-ce seulement possible?

Dans les exemples, nous pouvons voir:

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: ''};

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  handleSubmit(event) {
    alert('A name was submitted: ' + this.state.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input type="text" value={this.state.value} onChange={this.handleChange} />
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

En raison de la nature de mon travail, je suis souvent obligé de mettre en œuvre de telles formes. De plus, je ne dispose pas add ou removeinput directement - je gère des composants personnalisés, mais par souci de simplicité, je demande des éléments de formulaire de base.

14
Martin Shishkov

Comment ajouter/supprimer des éléments d'entrée dynamiquement possible?

Oui, c'est possible, vous pouvez ajouter/supprimer des éléments input, des éléments dynamically, mais pour cela, vous devez prendre soin de peu de choses:

1- Liaison correcte des événements.

2- Tableau pour stocker les valeurs de chaque élément d'entrée séparément.

3- Lorsque l'utilisateur remplit une valeur dans un élément d'entrée, il met à jour uniquement cette valeur spécifique dans l'état.

Logique:

Maintenir un tableau à l'intérieur de l'état, qui stockera les valeurs. Utilisez # array.map pour créer ui (élément d’entrée) pour chaque valeur de tableau. lors de la création des champs, utilisez remove button avec chaque champ et transmettez l'index du champ dans cette function. Cela vous aidera à identifier le champ que vous souhaitez supprimer. Faites la même chose pour onChange.

Vérifiez cet exemple:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { values: [] };
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  createUI(){
     return this.state.values.map((el, i) => 
         <div key={i}>
    	    <input type="text" value={el||''} onChange={this.handleChange.bind(this, i)} />
    	    <input type='button' value='remove' onClick={this.removeClick.bind(this, i)}/>
         </div>          
     )
  }

  handleChange(i, event) {
     let values = [...this.state.values];
     values[i] = event.target.value;
     this.setState({ values });
  }
  
  addClick(){
    this.setState(prevState => ({ values: [...prevState.values, '']}))
  }
  
  removeClick(i){
     let values = [...this.state.values];
     values.splice(i,1);
     this.setState({ values });
  }

  handleSubmit(event) {
    alert('A name was submitted: ' + this.state.values.join(', '));
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
          {this.createUI()}        
          <input type='button' value='add more' onClick={this.addClick.bind(this)}/>
          <input type="submit" value="Submit" />
      </form>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('container'));
<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='container'/>

Vérifiez le jsfiddle de travail: https://jsfiddle.net/mayankshukla5031/ezdxg224/

27
Mayank Shukla
import React, { Component, } from 'react';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
var childJson = []
export default class AddInvoice extends Component {
constructor(props) {
    super(props);
    this.state = {
        Json: [],
        rows: [{}]
    }
}

handleChange = idx => e => {
    const { name, value } = e.target;
    const rows = [...this.state.rows];
    rows[idx] = { [name]: value };
    this.setState({ rows });

    console.log(`rows-->>${this.state.rows[idx].amount}`);
    childJson.Push(this.dynamicJson(this.state.rows, idx))
    this.setState({ Json: childJson })

};
handleAddRow = () => {
    const item = {
        name: "",
        mobile: "",
        btn: ""
    };
    this.setState({
        rows: [...this.state.rows, item]
    });
};
handleRemoveRow = (idx) => {
    this.state.rows.splice(idx, 1);
    this.setState({ rows: this.state.rows });
};
dynamicJson(rows, index) {
    return {
        "service": rows[index].text,
        "tax": rows[index].tax,
        "amount": rows[index].amount
    }
};
render() {
    return (
        <div className="ui one column grid">
            <div className=" row">
                <div className="one wide computer one wide tablet one wide mobile column">
                </div>
                <div className="fourteen wide computer fourteen wide tablet fourteen wide mobile column">
                    <h1 id="title_header">INVOICE-ADD NEW</h1>
                </div>
                <div className="one wide computer one wide tablet one wide mobile column">
                </div>
            </div>
            <div className=" row">
                <div className="one wide computer one wide tablet one wide mobile column">
                </div>
                <div className="fourteen wide computer fourteen wide tablet fourteen wide mobile column">
                    <div id="#cus_segment" className="ui segment" style={{ backgroundColor: '#f5f5f5' }}>
                        <div className="ui form">
                            <div className="ui  stackable grid">
                                <div className="six wide column">
                                    <div className="field">
                                        <label>Invoice No</label>
                                        <input type="text" name="invoiceno" placeholder="Invoice No" value={this.state.invoiceno} onChange={e => this.setState({ invoiceno: e.target.value })} />
                                    </div>
                                </div>
                                <div className=" six wide column">
                                    <div className="field">
                                        <label>Customer</label>
                                        <select className="ui fluid selection search dropdown" name="customer" value={this.state.customer} onChange={e => this.setState({ customer: e.target.value })}>
                                            <option defaultValue="">select</option>
                                            <option value="[email protected]">[email protected]</option>
                                            <option value="[email protected]">[email protected]</option>
                                            <option value="[email protected]">[email protected]</option>
                                            <option value="[email protected]">[email protected]</option>
                                        </select>
                                    </div>
                                </div>
                                <div className="one row">
                                    <div className="six wide column">
                                        <div className="field">
                                            <label>Invoice Date</label>
                                            <div className="ui calendar" id="calender1">
                                                <div className="ui input right icon">
                                                    <i className="calendar icon"></i>
                                                    <input type="text" placeholder="Invoice Date" value={this.state.invoicedate} onBlur={e => this.setState({ invoicedate: e.target.value })} />
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                    <div className="six wide column">
                                        <div className="field">
                                            <label>Due Date</label>
                                            <div className="ui calendar" id="calender2">
                                                <div className="ui input right icon">
                                                    <i className="calendar icon"></i>
                                                    <input type="text" placeholder="Due Date" value={this.state.duedate} onBlur={e => this.setState({ duedate: e.target.value })} />
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                                <div className="two row">
                                    <div className="six wide column">
                                        <div className="field">
                                            <label>Header</label>
                                            <input type="text" name="header" placeholder="Header" value={this.state.header} onChange={e => this.setState({ header: e.target.value })} />
                                        </div>
                                    </div>
                                    <div className="six wide column">
                                        <div className="field">
                                            <label>Remark</label>
                                            <input type="text" name="remark" placeholder="Remark" value={this.state.remark} onChange={e => this.setState({ remark: e.target.value })} />
                                        </div>
                                    </div>
                                </div>
                                <div className="three row">
                                    <div className="ten wide column">
                                        <button className="ui primary button" type="submit">Save</button>
                                        <button className="ui  button" type="submit">Clear</button>
                                        <button className="ui  button" type="submit">Cancel</button>
                                    </div>
                                </div>

                                <div className="foure row">
                                    <div className="one wide column">
                                        <div className="field">
                                            <h4 style={{ textAlign: "center", borderRadius: 2 }}>Action</h4>
                                        </div>
                                    </div>
                                    <div className="two wide column" style={{ marginLeft: 55 }}>
                                        <div className="field">
                                            <h4 style={{ textAlign: "center", borderRadius: 2 }}>Text</h4>
                                        </div>
                                    </div>
                                    <div className="three column" style={{ marginLeft: 200 }}>
                                        <div className="field">
                                            <h4 style={{ textAlign: "center", borderRadius: 2 }}>Tax</h4>
                                        </div>
                                    </div>
                                    <div className="foure wide column" style={{ marginLeft: 190 }}>
                                        <div className="field">
                                            <h4 style={{ textAlign: "center", borderRadius: 2 }}>Amount</h4>
                                        </div>
                                    </div>
                                </div>
                                {this.state.rows.map((item, idx) => (
                                    <div className="five row" id="addr0" key={idx} >
                                        <div className="one wide column">
                                            <div className="field">
                                                <div className="ui icon" style={{ backgroundColor: "#f76060", color: "white", height: 35, width: 40, textAlign: "center", borderRadius: 2 }} onClick={() => this.handleRemoveRow(idx)}>
                                                    <i className="trash alternate icon" style={{ marginTop: 8 }}></i>
                                                </div>
                                            </div>
                                        </div>

                                        <div className="five wide column">
                                            <div className="field">
                                                <input type="text" name="text" placeholder="text" value={this.state.rows[idx].text} onChange={this.handleChange(idx)} />
                                            </div>
                                        </div>

                                        <div className="three wide column">
                                            <div className="field">
                                                <select className="ui fluid selection search dropdown " name="tax" id="tax_dropdown" value={this.state.rows[idx].tax} onChange={this.handleChange.bind(this)}>
                                                    <option defaultValue="">Select</option>
                                                    <option value="STAX">STAX</option>
                                                    <option value="VAT">VAT</option>
                                                </select>
                                            </div>
                                        </div>

                                        <div className="three wide column">
                                            <div className="field">
                                                <input type="text" name="amount" placeholder="amount" value={this.state.rows[idx].amount} onChange={this.handleChange(idx)} />
                                            </div>
                                        </div>
                                    </div>

                                ))}
                                <div className="six row">
                                    <div className="two wide column">
                                        <div className="field">
                                            <div className="ui icon" style={{ backgroundColor: "#c4d3d3", height: 35, width: 55, textAlign: "center", borderRadius: 2 }} onClick={this.handleAddRow}>
                                                <i className="plus icon" style={{ marginTop: 8 }}></i>
                                                <label>Add</label>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                <div className="one wide computer one wide tablet one wide mobile column">
                </div>
            </div>

        </div>
    );
}

}

0

Vous pouvez facilement utiliser votre état ou les accessoires que vous passez à partir d'autres composants pour décider de ce que votre formulaire devrait être. 

Voici un exemple stupide:

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: ''};

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  handleSubmit(event) {
    alert('A name was submitted: ' + this.state.value);
    event.preventDefault();
  }

  render() {
    let myForm;
    if(this.props.someprop == true){
       myForm = (
           <form onSubmit={this.handleSubmit}>
              <label>
                 Name:
                 <input type="text" value={this.state.value} onChange=      {this.handleChange} />
              </label>
              <input type="submit" value="Submit" />
           </form>
       );
    }
    else if(this.state.statevar == "expectedValue"){
        myForm = (
           // other HTML with embedded JS here
        );
    }


    return (
         {myForm}
    );
  }
}

Je l'ai fait dans la méthode de rendu juste pour être clair mais toute la logique peut être déplacée dans des fonctions auxiliaires.

0
rakwaht