Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reset a form except one field with Javascript

For some reason, I need to reset a form but I want one field to remain unchanged.

This following code clears all the fields but I would like to keep the first one unchanged.

<form id="myForm">
    <input id="01" type="text"/>
    <input id="02" type="text"/>
    <input id="03" type="text"/>
    <input id="04" type="text"/>
</form>
<button onclick="document.getElementById('myForm').reset()">Reset</button>

If possible, I would like to avoid jQuery.

like image 282
vcuongvu Avatar asked Dec 03 '14 09:12

vcuongvu


People also ask

How do you reset form fields?

The HTMLFormElement. reset() method restores a form element's default values. This method does the same thing as clicking the form's <input type="reset"> control. If a form control (such as a reset button) has a name or id of reset it will mask the form's reset method.

What does reset () do in JavaScript?

In JavaScript, the reset() method does the same thing as the HTML reset button. It is used to clear all the values of the form elements. It can be used to set the values to default. It does not require any parameter values and also does not return any value.

How do you clear form data after submit in JavaScript?

To clear an input field after submitting:Add a click event listener to a button. When the button is clicked, set the input field's value to an empty string. Setting the field's value to an empty string resets the input.

How do you clear a form value?

The reset() method resets the values of all elements in a form (same as clicking the Reset button).


2 Answers

Copy its value to a variable. Reset the form. Reassign the variable back to the value.

like image 190
Quentin Avatar answered Oct 04 '22 05:10

Quentin


I had been working on an answer to this question, which is similar, and has now been marked as a duplicate. That question was using jQuery, so the answer would have been much shorter, leveraging things like event.data, detach(), etc. Below is the general algorithm, and a vanilla version of the approach I would take to handle not just this question's but also more complex scenarios where you want to exclude an entire subsection of a form.


The algorithm

  1. Detach the element from it's parent
  2. Allow the default reset() behavior
  3. Reattach the element in the correct location within the DOM

Here is a very simple translation of that plan in to code. This doesn't actually re-attach the element in the right location within the DOM. Please see the code snippet for a fully functional example.

// within the form's onreset handler, which fires
// before the form's children are actually reset

var form = document.getElementById("myForm"),
    exclude = document.getElementById("_01"),
    parentNode = exclude.parentNode;

parentNode.removeChild(exclude);

// use a timeout to allow the default reset() behavior
// before re-attaching the element
setTimeout(function() { parentNode.appendChild(exclude); });

NOTE the id change to _01, and refer to the "Side note" at the end of this answer for more info on that.


Important properties and methods

  • .parentNode
  • .nextSibling
  • .removeChild()
  • .appendChild()
  • .insertBefore()

var dataKey = 'data-exclude-selector';

function initiateReset(e) {
  e = e || window.event;

  var button = e.target,
    form = button.form,
    excludeSelector = button.getAttribute(dataKey);

  form.setAttribute(dataKey, excludeSelector);
}

function beforeReset(e) {
  e = e || window.event;

  var form = e.target,
    excludeSelector = form.getAttribute(dataKey),
    elements = form.querySelectorAll(excludeSelector),
    parents = [],
    siblings = [],
    len = elements.length,
    i, e, p, s;

  // When reset #5 is clicked, note the excludeSelector's value is js escaped:
  // #\0030\0035 element attribute value becomes #\\0030\\0035 as js var value

  for (i = 0; i < len; i++) {
    el = elements[i];
    parents.push(p = el.parentNode);
    siblings.push(s = el.nextSibling);
    p.removeChild(el);
  }

  setTimeout(function() {
    for (var j = 0; j < len; j++) {
      if (siblings[j]) {
        parents[j].insertBefore(elements[j], siblings[j]);
      } else {
        parents[j].appendChild(elements[j]);
      }
    }
  });
}
<form id="myForm" onreset="beforeReset()" data-exclude-selector="">
  <input id="_01" type="text" placeholder="clear" />
  <br />
  <input id="_02" type="text" placeholder="clear" />
  <br />
  <input id="_03" type="text" placeholder="clear" />
  <br />
  <input id="_04" type="text" placeholder="clear" />
  <br />
  <input id="05" type="text" placeholder="clear" />
</form>
<input value="Reset 1" type="reset" form="myForm" data-exclude-selector="#_01" onclick="initiateReset()" />
<input value="Reset 2" type="reset" form="myForm" data-exclude-selector="#_02" onclick="initiateReset()" />
<input value="Reset 3" type="reset" form="myForm" data-exclude-selector="#_03" onclick="initiateReset()" />
<input value="Reset 4" type="reset" form="myForm" data-exclude-selector="#_04" onclick="initiateReset()" />
<input value="Reset funky ID (05)" type="reset" form="myForm" data-exclude-selector="#\0030\0035" onclick="initiateReset()" />
<br/>&nbsp;
<br />
<hr/>
<br/>
<form id="complexForm" onreset="beforeReset()" data-exclude-selector="">
  <input class="exclude" type="text" placeholder="clear" />
  <br />
  <input class="exclude" type="text" placeholder="clear" />
  <br />
  <input type="text" placeholder="clear" />
  <br />
  <input type="text" placeholder="clear" />
  <br />
  <div class="childTest">
    <input type="text" placeholder="clear" />
    <br />
    <input type="text" placeholder="clear" />
    <div class="nestedTest">
      <input type="text" placeholder="clear" />
      <br />
      <input type="text" placeholder="clear" />
    </div>
  </div>
</form>
<input value="Exclude by class" type="reset" form="complexForm" data-exclude-selector=".exclude" onclick="initiateReset()" />
<input value="Exclude subsection" type="reset" form="complexForm" data-exclude-selector=".childTest" onclick="initiateReset()" />

Additional work

  • More work will need to be done to handle the case where one would want to allow reset on certain children of excluded nodes, but I imagine this could be handled in multiple different ways with a little thought

    1. a recursive version of this idea
    2. @Quentin's idea could be extended using cloneNode() to make a copy of the entire node, instead of detaching it, allow a full reset, then implement a mechanism to determine which portions of the clone to systematically restore

Side note (...rant?)

  • Although the HTML5 id attribute allows for 01 as valid, the spec does go on to indicate that it can be used for other purposes.

3.2.5.1 The id attribute

The id attribute specifies its element's unique identifier (ID). [DOM]

The value must be unique amongst all the IDs in the element's home subtree and must contain at least one character. The value must not contain any space characters.

Note: There are no other restrictions on what form an ID can take; in particular, IDs can consist of just digits, start with a digit, start with an underscore, consist of just punctuation, etc.

Note: An element's unique identifier can be used for a variety of purposes, most notably as a way to link to specific parts of a document using fragment identifiers, as a way to target an element when scripting, and as a way to style a specific element from CSS.

This may not be a problem for you, but it is something to be aware of. For instance, document.querySelector[All]() uses CSS style selectors.

elementList = document.querySelectorAll(selectors);

...

  • selectors is a string containing one or more CSS selectors separated by commas.

According to the latest draft of the CSS Selectors spec

An ID selector contains a "number sign" (U+0023, #) immediately followed by the ID value, which must be an CSS identifiers.

And at the end of the rabbit hole are the rules for CSS identifiers

  • In CSS, identifiers (including element names, classes, and IDs in selectors) can contain only the characters [a-zA-Z0-9] and ISO 10646 characters U+00A0 and higher, plus the hyphen (-) and the underscore (_); they cannot start with a digit, two hyphens, or a hyphen followed by a digit. Identifiers can also contain escaped characters and any ISO 10646 character as a numeric code (see next item). For instance, the identifier "B&W?" may be written as "B\&W\?" or "B\26 W\3F".

    Note that Unicode is code-by-code equivalent to ISO 10646 (see [UNICODE] and [ISO10646]).

So if you're only using document.getElementById() you might be ok with an element id value like 01, but in general I would avoid it. Yes, with document.querySelector[All](), and any other component that uses CSS style selectors you may be able to get around this limitation by escaping the selector correctly, but this is a pitfall waiting to happen, especially if multiple developers are involved. I've included an example (5th reset button) in the code snippet for completion, if you have to interact with elements that have IDs taking a format like this.

Reference table for hex codes

like image 22
Eric Lease Avatar answered Oct 04 '22 04:10

Eric Lease