Stellen Sie den Optionsfeldwert in Reagieren ein

Nov 24 2020

Ich mache eine einfache Reaktions-App mit Formular, das Optionsfelder hat.

Hier sind Standarddaten verfügbar wie:

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

Anforderung:

-> Sie müssen dies wiederholen defaultDataund den jeweiligen ContactModeModus zuweisen, wie in jeder Zeile markiert .

Arbeitsausschnitt:

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>

Erwartete Ausgabe:

Contact Mode  Email Text Both (Checked)

Contact Mode  Email Text(Checked) Both

Contact Mode  Email Text(Checked) Both

Hinweis: Ich kann das Namensattribut nicht ändern name="ContactMode". Grund dafür ist, dass ich in jeder Zeile eine eigene Schaltfläche zum Speichern habe und beim Klicken auf diese Schaltfläche zum Speichern diese bestimmte Zeile gespeichert wird. Und jede Zeile sollte haben name="ContactMode".

Bearbeiten:

Da meine Frage nicht klar ist, was ich erreichen möchte, werde ich hier den gesamten Code angeben.

-> Ich habe ein Schrittformular, in dem Schritt 2 der Beschäftigungsabschnitt ist, und standardmäßig habe ich die Werte, die in das Formular gesetzt werden sollen.

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

-> Innerhalb des useEffectHakens setze ich den Formularwert wie folgt:

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

Hier werden die Formularwerte mit Eingabefeldern ordnungsgemäß gebunden, der Optionsfeldwert wird jedoch nicht aktiviert.

-> Es sind zwei Daten verfügbar, aber die erste wird standardmäßig erweitert und die zweite wird durch Klicken auf die ExpandSchaltfläche unter der ersten geöffnet .

-> Beim Klicken auf die saveSchaltfläche wird dieses bestimmte Objekt ( inputField) zusammen mit geänderten Daten in der Konsole protokolliert (nur Testen).

Hier ist das Problem, wenn wir die Daten ändern, dann funktionieren die Dinge gut, aber das Radio-Checked-Attribut allein macht das Element nicht überprüft. (Überprüfte Anzeige funktioniert nicht).

Fahren Sie mit Schritt 2 in der unten angegebenen Codesandbox fort, um das Problem anzuzeigen. Um das zweite Element anzuzeigen, klicken Sie auf die Schaltfläche zum Erweitern.

Bitte helfen Sie mir, den Standardwert für das Optionsfeld in jeder Zeile festzulegen.

Antworten

1 DrewReese Nov 25 2020 at 14:15

In Ihrer Sandbox konnte ich die Optionsfelder zum Laufen bringen

  1. Bereitstellung einer eindeutigen Funktion namefür jede zugeordnete Funkgruppe
  2. Aktualisieren Sie den Änderungshandler, um die ContactModeEigenschaft eindeutig zu behandeln .

Aktualisieren Sie die Funkgruppen, um den aktuellen zugeordneten Index zu verwenden, damit sie für alle zugeordneten Gruppen eindeutig sind.

<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>

Im handleInputChangeAdd auf einen Fall zu behandeln ContactModespeziell.

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

Ich denke, aufgrund dessen, dass alle Funkgeräte das gleiche Namensattribut haben, sollte jede Gruppe einen anderen Namen haben. zum Beispiel:

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

für jede neue Gruppe fälliger Name wie dieser. wenn Sie den gleichen Namen tun es alles machen verkorkste andere denken , dass Sie ==statt===

item.ContactMode == 3

es ist besser zu benutzen ===

vkvkvk Nov 24 2020 at 22:49

@ TalOrlanczyks Antwort ist richtig. Sie drucken insgesamt 9 Optionsfelder und alle haben den gleichen Wert im Namensattribut. Technisch ist es also so, als hätte man eine Radiogruppe mit 9 Optionsfeldern, was bedeutet, dass eine Radiogruppe nur einen Wert akzeptieren kann. Ich habe Ihren Code ausgeführt und nur "Text" in der 3. Zeile ausgewählt.

Wenn Sie versuchen, 3 separate Zeilen (Funkgruppen) zu haben, müssen Sie Folgendes versuchen:

<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)}
/>{" "}

Probieren Sie es aus und führen Sie Ihren Code erneut aus

NeetigyaChahar Nov 25 2020 at 13:16

Hier sind einige Probleme in Ihrem Code ...

  1. Jedes Mal, wenn die Komponente zurückkehrt, .mapwird die aufgerufen defaultData. Daher nicht dem Zustand zugeordnet.

  2. Wenn Sie für jede Iteration den gleichen Namen möchten, müssen Sie <form>für jede Iteration alle anderen Optionsfelder zusammen gruppieren. Daher wird nur das letzte Optionsfeld als markiert angezeigt.

  3. Es ist besser zu verwenden ===als==

Ich habe Ihren Code geändert und defaultDatawird verwendet, um den Status zu initialisieren.

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>