Ustaw wartość przycisku opcji w Reakcie
Tworzę prostą aplikację do reagowania z formularzem, który ma przyciski opcji.
Tutaj dostępne są domyślne dane, takie jak:
const defaultData = [{ ContactMode: 3 }, { ContactMode: 2 }, { ContactMode: 2 }];
Wymaganie:
-> Trzeba to powtórzyć defaultData
i przypisać odpowiedni ContactMode
tryb jako zaznaczony w każdym wierszu.
Działający fragment:
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>
Oczekiwany wynik:
Contact Mode Email Text Both (Checked)
Contact Mode Email Text(Checked) Both
Contact Mode Email Text(Checked) Both
Uwaga: nie mogę zmodyfikować atrybutu nazwy name="ContactMode"
. Powodem jest to, że mam również oddzielny przycisk zapisywania w każdym wierszu i po kliknięciu tego przycisku zapisywania ten konkretny wiersz zostanie zapisany .. I każdy wiersz powinien mieć name="ContactMode"
...
Edytować:
Ponieważ moje pytanie nie jest jasne, co próbuję osiągnąć, podam tutaj cały kod.
-> Mam formularz steppera w którym Step 2 to sekcja zatrudnienia i domyślnie mam wartości do ustawienia w formularzu,
const dynamicData = [
{
EmploymentID: 1,
companyName: 'Company One',
designation: 'Designation One',
ContactMode: 3,
},
{
EmploymentID: 2,
companyName: 'Company two',
designation: 'Designation One',
ContactMode: 2,
},
];
-> Inside useEffect
hook ustawiam wartość formularza jak,
React.useEffect(() => {
setExpanded(0);
setValue((prev) => {
const companyDetails = [...dynamicData];
return { ...prev, companyDetails };
});
}, []);
Tutaj wartości formularza z polami wejściowymi są odpowiednio powiązane, ale wartość przycisku opcji nie jest sprawdzana.
-> Dostępne są dwie dane, ale pierwsza zostanie domyślnie rozwinięta, a druga zostanie otwarta po kliknięciu Expand
przycisku poniżej pierwszej.
-> Po kliknięciu save
przycisku ten konkretny obiekt ( inputField
) zostanie zalogowany do konsoli (tylko testowanie) wraz ze zmodyfikowanymi danymi.
Tutaj PROBLEM polega na tym, że jeśli zmodyfikujemy dane, wszystko działa dobrze, ale sam atrybut sprawdzony przez radio nie powoduje sprawdzenia pozycji ... (zaznaczone wskazanie nie działa) ..
Aby zobaczyć problem, przejdź do kroku 2 w podanym poniżej polu kodów. Aby zobaczyć drugą pozycję, kliknij przycisk rozwijania.
Uprzejmie proszę o pomoc w ustawieniu domyślnej wartości przycisku opcji w każdym wierszu.
Odpowiedzi
W twojej piaskownicy udało mi się uruchomić przyciski radiowe
- Zapewnienie unikalnej
name
dla każdej mapowanej grupy radiowej - Zaktualizuj procedurę obsługi zmian, aby unikatowo obsługiwać
ContactMode
właściwość.
Zaktualizuj grupy radiowe, aby korzystały z bieżącego mapowanego indeksu, aby były unikalne wśród wszystkich mapowanych grup.
<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>
W handleInputChange
dodatku przypadek do obsługi ContactMode
specjalnie.
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 };
});
};
Myślę, że ze względu na to, że wszystkie radia mają ten sam atrybut nazwy, każda grupa powinna mieć inną nazwę. na przykład:
name = " ex1"
name = "ex2"
name = "ex3"
dla każdej nowej grupy należy nadać taką nazwę. jeśli zrobisz to samo imię, wszystko schrzanisz, a inni pomyślą o tobie ==
zamiast===
item.ContactMode == 3
lepiej jest użyć ===
Odpowiedź @ TalOrlanczyk jest prawidłowa. W sumie drukujesz 9 przycisków opcji i wszystkie mają tę samą wartość w atrybucie nazwy. Z technicznego punktu widzenia jest to tak, jakby mieć grupę radiową z 9 przyciskami opcji, co oznacza, że grupa radiowa może przyjąć tylko jedną wartość. Uruchomiłem twój kod i zaznaczyłem tylko "Tekst" w 3. linii.
Jeśli próbujesz mieć 3 oddzielne wiersze (grupy radiowe), musisz spróbować czegoś takiego:
<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)}
/>{" "}
Wypróbuj i ponownie uruchom kod
Oto kilka problemów w Twoim kodzie ...
Za każdym razem, gdy składnik powraca,
.map
wywoływana jest metodadefaultData
. W związku z tym nie przypisano do stanu.Jeśli chcesz mieć taką samą nazwę dla każdej iteracji, musisz użyć
<form>
dla każdej iteracji wszystkich innych przycisków radiowych, które zostaną zgrupowane razem, dlatego tylko ostatni przycisk opcji będzie wyświetlany jako zaznaczony.Lepiej jest używać
===
zamiast==
Zmodyfikowałem twój kod i defaultData
jest używany do inicjalizacji stanu.
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>