Définir la valeur du bouton radio dans React
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 defaultData
et d'assigner leur ContactMode
mode 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 useEffect
crochet, 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 Expand
bouton en dessous de la première.
-> En cliquant sur le save
bouton, 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
Dans votre bac à sable, j'ai pu faire fonctionner les boutons radio
- Fournir un unique
name
pour chaque groupe radio mappé - Mettez à jour le gestionnaire de modifications pour gérer de manière unique la
ContactMode
proprié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 handleInputChange
ajouter un cas à manipuler ContactMode
spé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 };
});
};
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 ===
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
Voici quelques problèmes dans votre code ...
Chaque fois que le composant revient, le
.map
est appelédefaultData
. Donc pas mappé à l'état.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é.Il vaut mieux utiliser
===
au lieu de==
J'ai modifié votre code et defaultData
sert à 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>