skip to Main Content

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?

2

Answers


  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, 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...
      }
    }
    
    Login or Signup to reply.
  2. 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>

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search