Définir la valeur du bouton radio dans React

Nov 24 2020

Je crée une application de réaction simple avec un formulaire doté de boutons radio.

Ici, il y a une donnée par défaut disponible comme,

const defaultData = [{ ContactMode: 3 }, { ContactMode: 2 }, { ContactMode: 2 }];

Exigence:

-> Besoin d'itérer ceci defaultDataet d'assigner leur ContactModemode respectif comme coché dans chaque ligne.

Extrait de travail:

const { useState } = React;

const App = () => {
  const [formValue, setFormValue] = useState({
    ContactMode: 1
  });

  const defaultData = [{ ContactMode: 3 }, { ContactMode: 2 }, { ContactMode: 2 }];

  const handleInputChange = (e, index) => {
    const { name, value } = event.target;
    setFormValue({
      ...formValue,
      [name]: value
    });
  };

  const submitData = () => {
    console.log(formValue);
  };

  return (
    <div>
      <form>
        {defaultData.map((item, index) => {
          return (<React.Fragment>
            <label> Contact Mode </label>
            <input
              type="radio"
              name="ContactMode"
              checked={item.ContactMode == 1}
              value={1}
              onChange={(event) => handleInputChange(index, event)}
            />{" "}
            Email
            <input
              type="radio"
              name="ContactMode"
              checked={item.ContactMode == 2}
              value={2}
              onChange={(event) => handleInputChange(index, event)}
            />{" "}
            Text
            <input
              type="radio"
              name="ContactMode"
              checked={item.ContactMode == 3}
              value={3}
              onChange={(event) => handleInputChange(index, event)}
            />{" "}
            Both
            <br />
            <br />
            <button type="button">
               Save
             </button>
            <br />
            <br />
            <br />
          </React.Fragment>);
        })}
      </form>
    </div>
  );
};

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.11.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>

Production attendue:

Contact Mode  Email Text Both (Checked)

Contact Mode  Email Text(Checked) Both

Contact Mode  Email Text(Checked) Both

Remarque: je ne peux pas modifier l'attribut de nom name="ContactMode". La raison est que j'ai également un bouton d'enregistrement individuel pour chaque ligne et en cliquant sur ce bouton d'enregistrement, cette ligne particulière sera enregistrée. Et chaque ligne devrait avoir name="ContactMode"..

Éditer:

Comme ma question n'est pas claire sur ce que j'essaie de réaliser, je vais donner le code entier ici.

-> J'ai un formulaire stepper dans lequel l'étape 2 est la section emploi et par défaut j'ai les valeurs à définir dans le formulaire,

const dynamicData = [
  {
    EmploymentID: 1,
    companyName: 'Company One',
    designation: 'Designation One',
    ContactMode: 3,
  },
  {
    EmploymentID: 2,
    companyName: 'Company two',
    designation: 'Designation One',
    ContactMode: 2,
  },
];

-> À l'intérieur du useEffectcrochet, j'ai défini la valeur du formulaire comme,

  React.useEffect(() => {
    setExpanded(0);
    setValue((prev) => {
      const companyDetails = [...dynamicData];
      return { ...prev, companyDetails };
    });
  }, []);

Ici, les valeurs de formulaire avec des zones de saisie sont correctement liées mais la valeur du bouton radio n'est pas cochée.

-> Il y a deux données disponibles mais la première sera développée par défaut et alors que la seconde sera ouverte en cliquant sur le Expandbouton en dessous de la première.

-> En cliquant sur le savebouton, cet objet particulier ( inputField) sera consigné par la console (test uniquement) avec les données modifiées.

Ici, le PROBLÈME est que si nous modifions les données, les choses fonctionnent bien, mais l'attribut radio vérifié seul ne rend pas l'élément vérifié. (L'indication cochée ne fonctionne pas).

Veuillez passer à l'étape 2 dans les codes et la boîte ci-dessous pour voir le problème. Pour voir le deuxième élément, cliquez sur le bouton Développer.

Merci de bien vouloir m'aider à définir la valeur par défaut du bouton radio dans chaque ligne.

Réponses

1 DrewReese Nov 25 2020 at 14:15

Dans votre bac à sable, j'ai pu faire fonctionner les boutons radio

  1. Fournir un unique namepour chaque groupe radio mappé
  2. Mettez à jour le gestionnaire de modifications pour gérer de manière unique la ContactModepropriété.

Mettez à jour les groupes radio pour utiliser l'index mappé actuel afin de les rendre uniques parmi tous les groupes mappés.

<div className="form-group col-sm-4">
  <label className="inline-flex items-center mr-6">
    <input
      type="radio"
      className="form-radio border-black"
      name={`ContactMode-${index}`} // <-- append index to name value={1} checked={inputField.ContactMode === 1} // <-- use strict "===" onChange={(event) => handleInputChange(index, event)} /> <span className="ml-2">Email</span> </label> </div> <div className="form-group col-sm-4"> <label className="inline-flex items-center mr-6"> <input type="radio" className="form-radio border-black" name={`ContactMode-${index}`}
      value={2}
      checked={inputField.ContactMode === 2}
      onChange={(event) => handleInputChange(index, event)}
    />
    <span className="ml-2">Text</span>
  </label>
</div>
<div className="form-group col-sm-4">
  <label className="inline-flex items-center mr-6">
    <input
      type="radio"
      className="form-radio border-black"
      name={`ContactMode-${index}`}
      value={3}
      checked={inputField.ContactMode === 3}
      onChange={(event) => handleInputChange(index, event)}
    />
    <span className="ml-2">Both</span>
  </label>
</div>

Dans le handleInputChangeajouter un cas à manipuler ContactModespécialement.

const handleInputChange = (index, event) => {
  const { name, value } = event.target;
  if (name === 'designation' && !isLettersOnly(value)) {
    return;
  }

  if (name.startsWith('ContactMode')) { // <-- check name prefix
    setValue((prev) => ({
      ...prev,
      companyDetails: prev.companyDetails.map((detail, i) =>
        i === index
          ? {
              ...detail,
              ContactMode: Number(value), // <-- store back under correct key, as number for string equality check
            }
          : detail,
      ),
    }));
    return; // <-- return early so other state update is skipped!
  }

  setValue((prev) => {
    const companyDetails = prev.companyDetails.map((v, i) => {
      if (i !== index) {
        return v;
      }

      return { ...v, [name]: value };
    });

    return { ...prev, companyDetails };
  });
};

1 TalOrlanczyk Nov 24 2020 at 22:10

Je pense que c'est à cause du fait que toutes les radios ont le même attribut de nom, chaque groupe devrait avoir un nom différent. par exemple:

name = " ex1"
name = "ex2"
name = "ex3"

pour chaque nouveau nom de groupe comme celui-ci. si vous faites le même nom, tout est gâché, un autre vous pense ==au lieu de===

item.ContactMode == 3

il vaut mieux utiliser ===

vkvkvk Nov 24 2020 at 22:49

La réponse de @ TalOrlanczyk est juste. Vous imprimez 9 boutons radio au total et tous ont la même valeur dans l'attribut de nom. Donc techniquement, c'est comme avoir un groupe radio avec 9 boutons radio, ce qui signifie qu'un groupe radio ne peut accepter qu'une seule valeur. J'ai exécuté votre code et il n'a sélectionné "Texte" que sur la 3e ligne.

Si vous essayez d'avoir 3 lignes distinctes (groupes de radio), vous devez essayer quelque chose comme ceci:

<input
    type="radio"
    name={"ContactMode"+index}
    checked={item.ContactMode == 1}
    value={1}
    onChange={(event) => handleInputChange(index, event)}
/>{" "}
Email
<input
    type="radio"
    name={"ContactMode"+index}
    checked={item.ContactMode == 2}
    value={2}
    onChange={(event) => handleInputChange(index, event)}
/>{" "}
Text
<input
    type="radio"
    name={"ContactMode"+index}
    checked={item.ContactMode == 3}
    value={3}
    onChange={(event) => handleInputChange(index, event)}
/>{" "}

Essayez-le et relancez votre code

NeetigyaChahar Nov 25 2020 at 13:16

Voici quelques problèmes dans votre code ...

  1. Chaque fois que le composant revient, le .mapest appelé defaultData. Donc pas mappé à l'état.

  2. Si vous voulez le même nom pour chaque itération, vous devez utiliser <form>pour chaque itération sinon tous les boutons radio seront regroupés, donc seul le dernier bouton radio apparaîtra comme marqué.

  3. Il vaut mieux utiliser ===au lieu de==

J'ai modifié votre code et defaultDatasert à initialiser l'état.

const { useState } = React;


  const defaultData = [{ ContactMode: 3 }, { ContactMode: 2 }, { ContactMode: 2 }];

const App = () => {

  const [formValue, setFormValue] = useState([...defaultData]);

  const handleInputChange = (index, e) => {
    const { name, value } = e.target;

    const newFormValue = [...formValue];
    newFormValue.splice(index,1,{[name]: value});
    
    setFormValue(newFormValue);
  };

  const submitData = () => {
    console.log(formValue);
  };

  return (
    <div>
        {formValue.map((item, index) => {
          return (<form>
            <label> Contact Mode </label>
            <input
              type="radio"
              name="ContactMode"
              checked={Number(item.ContactMode) === 1}
              value={1}
              onChange={(event) => handleInputChange(index, event)}
            />{" "}
            Email
            <input
              type="radio"
              name="ContactMode"
              checked={Number(item.ContactMode) === 2}
              value={2}
              onChange={(event) => handleInputChange(index, event)}
            />{" "}
            Text
            <input
              type="radio"
              name="ContactMode"
              checked={Number(item.ContactMode) === 3}
              value={3}
              onChange={(event) => handleInputChange(index, event)}
            />{" "}
            Both
            <br />
            <br />
          </form>);
        })}
        <button type="button" onClick={submitData}>
          {" "}
          Submit{" "}
        </button>
    </div>
  );
};

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.11.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>