3

Assuming there is an unknown list of input types in a form, so it can be a mix of many (radios, selects, texts etc..), and when the page refreshes I get a key-value object from the backend that represents the input names and their values, is it possible to set their values easily without knowing the type, or there are cases where just knowing the input name and value is not enough?

For example, the form:

<form id="myform">
    <input type="text" name="text1" />
    <input type="radio" name="radio1" />
    <input type="radio" name="radio2" />
    <select name="select1">
       <option value="1">1</option>
       <option value="2">2</option>
       <option value="3">3</option>
    </select> 
</form>

Then the data object from the backend:

{
    "text1": "foo",
    "radio1": "bar",
    "radio2": "hello",
    "select1": "world"    
}

Then this is the script I made

function setInputs(inputs) {
    let inputElement;
    for (const [key, value] of Object.entries(inputs)) {        
        inputElement = document.querySelector(`#myform [name='${key}']`);
        inputElement.value = value;
    }
}

But will it set all the inputs that are possible to set? Of course some inputs aren't possible, like type="file", but will my setInputs() function set what's possible? Or I need to cover more use cases and what I did is not enough?

3
  • 2
    Radio buttons are a little tricky, as are multiple selects... :) Commented May 2, 2023 at 17:44
  • 1
    You should provide a bigger 'test case' in the form of a form (pun intended) with all the input types you expect this to work with :) Commented May 2, 2023 at 17:45
  • 1
    Might consider the "type" ref: developer.mozilla.org/en-US/docs/Learn/Forms/HTML5_input_types re: type="email", type="select" and if it has a multiple attribute Commented May 2, 2023 at 18:05

2 Answers 2

1

Checkbox Fields

Checkboxes have 2 states in which we should concern ourselves with: true and false. If the server receives a checkbox [name]: value it is implied that it's true that it is checked. Set the checkbox as checked using the .checked property (see Example A).

Example A
const data = {
  chx: "TEST"
};
const checkbox = document.forms[0].elements["chx"];
checkbox.checked = true;
<form>
  <input name="chx" type="checkbox" value="TEST">
</form>

Radio Button Groups

The typical layout of radio buttons is as a group of two or more -- each having a specific value. A radio button group has a specific behavior in which the user can only check one radio button of said group. In order to ensure this behavior, each radio button of a group shares the same [name] (see Example B).

✱If there's only one value to be checked or unchecked, use a checkbox instead.

With the exception of checkboxes, direct assignment to the .value property will work.

Example B
/**
 * Set a given form's values derived from a given object 
 * by matching object key to a field's name attribute.
 * @param {Object} data - An object literal.
 * @param {number|string} form - A reference to a form by
 *        an index number or the form's #id or [name].
 *        @default is index number 0.
 */
function setVal(data, form = 0) {
  // Reference the <form>
  const main = document.forms[form];
  // Reference all form fields
  const fields = main.elements;
  // Get an array of all field [name]s
  const names = Array.from(fields).map(f => f.name);
  // Convert {Object} data into an array of key/value pairs
  const keyVal = Object.entries(data);
  
  // For each key/value pairs...
  keyVal.forEach(([key, val]) => {
    //... if the names array matches key...
    if (names.includes(key)) {
      //... and if the field is a checkbox...
      if (fields[key].type === "checkbox") {
        //... check the checkbox...
        fields[key].checked = true;
        //... otherwise...
      } else {
        //... assign the value of field to the value object
        fields[key].value = val;
      }
    }
  });
}

const data = {
  txt: "test",
  num: 7,
  area: `  test
  multiline
  data`,
  sel: "4",
  chx: "X",
  rad: "B"
};

setVal(data);
<form id="test">
  <fieldset>
    <legend>Direct Values</legend>
    <input name="txt" type="text"><br>
    <input name="num" type="number"><br>
    <textarea name="area" rows="3"></textarea><br>
    <select name="sel">
      <option value="1">I</option>
      <option value="2">II</option>
      <option value="3">III</option>
      <option value="4">IV</option>
    </select>
  </fieldset>
  <fieldset>
    <legend>Checked Values</legend>
    <input name="chx" type="checkbox" value="X"> X<br>
    <input name="rad" type="radio" value="A"> A
    <input name="rad" type="radio" value="B"> B
    <input name="rad" type="radio" value="C"> C
    <input name="rad" type="radio" value="D"> D
  </fieldset>
</form>

Sign up to request clarification or add additional context in comments.

Comments

1

This is ok for some input types, but not all of them. Instead of assigning value on this line of code:

inputElement.value = value;

I would call function which will do appropriate action:

function setInputs(inputs) {
    let inputElement;
    for (const [key, value] of Object.entries(inputs)) {        
        inputElement = document.querySelector(`#myform [name='${key}']`);
        assingInputValue(inputElement, value);
    }
}

function assingInputValue(inputElement, value) {
  switch (inputElement.type) {
    case 'text':
    case 'textarea':
    case 'number':
    case 'search':
      inputElement.value = value;
    break;
    case 'radio':
    case 'checkbox':
      // probably better to separate this to another function
      if (value === 'true' || value === true) {
         inputElement.setAttribute('checked', '');
      } else {
         inputElement.removeAttribute('checked');
      }
    break;
    case 'password':
      // WARNING: It is not safe to transfer passwords back to user in plain text.
    break;
    // others...
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.