Ad

Why My Input's Value Get Cleared When I Append A Child?

- 1 answer

I'm having trouble when I append an element inside a div and is that all the values from my inputs (including selected options) get cleared as is shown here:

problem

As you can see when I click the button "Añadir tecla", the text from the textbox and the selected option "Shift" goes back to default option that is "Flechas de movimiento".

Why this happens and how can I avoid it?

My code is the next:

var controls = [{value: "flechas", text: "Flechas de movimiento"}, {value: "letras", text: "Letras (WASD)"}, {value: "enter", text: "Enter"}, {value: "control", text: "Ctrl"}, {value: "alt", text: "Alt"}, {value: "espacio", text: "Espacio"}, {value: "der", text: "Click derecho"}, {value: "izq", text: "Click izquierdo"}, {value: "mover", text: "Mover el ratón"}, {value: "shift", text: "Shift"}, {value: "customkey", text: "Especificar tecla"}];

function addControl(e) 
{
    e.appendChild(getControlSelect());
}

function getControlSelect() 
{
    var select = document.createElement('select'),
        option,
        i = 0,
        il = controls.length,
        html = document.createElement('div'),
        text = document.createElement('input'),
        delbtn = document.createElement('input');

    text.type = "text";

    delbtn.type = "button";
    delbtn.value = "-";

    for (; i < il; ++i)
    {
        option = document.createElement('option');
        option.setAttribute('value', controls[i].value);
        option.appendChild(document.createTextNode(controls[i].text));
        select.appendChild(option);
    }
    html.innerHTML += "<b>Tecla</b><br>";
    html.appendChild(select);
    html.innerHTML += "<br><b>Acción</b><br>";
    html.appendChild(text);
    html.appendChild(delbtn);

    return html;
}

HTML Code:

<div>
    <input type="button" value="Añadir tecla" onclick="addControl(this.parentNode)" />
</div>

As you can see, when I click "Añadir tecla" I call addControl function with the parentNode as unique parameter (this will used later for append the child inside it).

So, I don't know where is the problem, I think everything is correct, but It need something to avoid the values get cleared.

EDIT: The code I shared hasn't problems, but my complete code has here:

var controls = [{value: "flechas", text: "Flechas de movimiento"}, {value: "letras", text: "Letras (WASD)"}, {value: "enter", text: "Enter"}, {value: "control", text: "Ctrl"}, {value: "alt", text: "Alt"}, {value: "espacio", text: "Espacio"}, {value: "der", text: "Click derecho"}, {value: "izq", text: "Click izquierdo"}, {value: "mover", text: "Mover el ratón"}, {value: "shift", text: "Shift"}, {value: "customkey", text: "Especificar tecla"}],
	skippedIndexes = [],
	sep = "<div class='sep' id='firstsep' style='width: 200px;'></div>",
	oldIndex = 0;//,
	//sInd = 0;

function addControl(e) 
{

	if(e.lastChild.className != "sep") e.innerHTML += sep;
	e.appendChild(getControlSelect());
	e.innerHTML += sep.replace(" id='firstsep'", "");
}

function onSelectChange(e) 
{
	//Modify the array
	//a = e.associatedInput

	//console.log(e.dataset.i);

	/*var newIndex;

	newIndex = e.selectedIndex;

	if(skippedIndexes.length > 0 && skippedIndexes.indexOf(oldIndex) > -1) skippedIndexes.splice(skippedIndexes.indexOf(oldIndex), 1); //Delete oldIndex

	if(skippedIndexes.length > 0 && skippedIndexes.indexOf(newIndex) == -1) skippedIndexes.push(newIndex);

	oldIndex = newIndex;*/

	//Change associated



}

function deleteFirstSep() 
{
	if(!document.getElementById("firstsep").nextSibling) document.getElementById("firstsep").remove();
}

function getControlSelect() 
{
	var select = document.createElement('select'),
	    option,
	    i = 0,
	    il = controls.length,
	    html = document.createElement('div'),
	    text = document.createElement('input'),
	    delbtn = document.createElement('input'),
	    ascinpt = document.createElement('input'),
	    html1 = document.createElement('div');

	html1.style.display = "inline-block";

	text.type = "text";
	text.name = "accion[]";
	text.style.width = "158px";

	delbtn.type = "button";
	delbtn.setAttribute('onclick', 'var e = this.parentNode;e.nextSibling.remove();e.remove();deleteFirstSep();');
	delbtn.value = "-";
	delbtn.style.padding = "0 5px";
	delbtn.style.marginLeft = "5px";
	delbtn.style.position = "relative";
	delbtn.style.top = "-20px";
	delbtn.style.left = "2px";

	ascinpt.name = "tecla[]";
	ascinpt.type = "hidden";

	select.id = "htmlkey";
	select.dataset.associatedInput = ascinpt;
	//select.dataset.i = sInd;
	//sInd++;
	select.setAttribute("onchange", "onSelectChange(this)");

	for (; i < il; ++i)
		if(skippedIndexes.indexOf(i) == -1) 
		{
		    option = document.createElement('option');
		    option.setAttribute('value', controls[i].value);
		    option.appendChild(document.createTextNode(controls[i].text));
		    select.appendChild(option);
		}
	html1.innerHTML += "<b>Tecla</b><br>";
	html1.appendChild(select);
	html1.innerHTML += "<br><b>Acción</b><br>";
	html1.appendChild(text);
	html.appendChild(html1);
	html.appendChild(delbtn);

	return html;
}
.sep {
  border-top: 4px dashed #A4A4A4;
  margin: 15px 0 15px 0;
}
<div>
    <input type="button" value="Añadir tecla" onclick="addControl(this.parentNode)" />
</div>

Ad

Answer

The problem is that you overwrite the HTML code

element.innerHTML += newHTML;

This gets rid of the state of the current elements, including event listeners, input values, checkedness, etc.

Instead, you should use appendChild or insertAdjacentHTML:

element.insertAdjacentHTML('beforeend', newHTML);

var controls = [{value: "flechas", text: "Flechas de movimiento"}, {value: "letras", text: "Letras (WASD)"}, {value: "enter", text: "Enter"}, {value: "control", text: "Ctrl"}, {value: "alt", text: "Alt"}, {value: "espacio", text: "Espacio"}, {value: "der", text: "Click derecho"}, {value: "izq", text: "Click izquierdo"}, {value: "mover", text: "Mover el ratón"}, {value: "shift", text: "Shift"}, {value: "customkey", text: "Especificar tecla"}],
  skippedIndexes = [],
  sep = "<div class='sep' id='firstsep' style='width: 200px;'></div>",
  oldIndex = 0; //,
//sInd = 0;

function addControl(e) {

  if (e.lastChild.className != "sep") e.innerHTML += sep;
  e.appendChild(getControlSelect());
  e.insertAdjacentHTML('beforeend', sep.replace(" id='firstsep'", ""));
}

function onSelectChange(e) {}

function deleteFirstSep() {
  if (!document.getElementById("firstsep").nextSibling) document.getElementById("firstsep").remove();
}

function getControlSelect() {
  var select = document.createElement('select'),
    option,
    i = 0,
    il = controls.length,
    html = document.createElement('div'),
    text = document.createElement('input'),
    delbtn = document.createElement('input'),
    ascinpt = document.createElement('input'),
    html1 = document.createElement('div');

  html1.style.display = "inline-block";

  text.type = "text";
  text.name = "accion[]";
  text.style.width = "158px";

  delbtn.type = "button";
  delbtn.setAttribute('onclick', 'var e = this.parentNode;e.nextSibling.remove();e.remove();deleteFirstSep();');
  delbtn.value = "-";
  delbtn.style.padding = "0 5px";
  delbtn.style.marginLeft = "5px";
  delbtn.style.position = "relative";
  delbtn.style.top = "-20px";
  delbtn.style.left = "2px";

  ascinpt.name = "tecla[]";
  ascinpt.type = "hidden";

  select.id = "htmlkey";
  select.dataset.associatedInput = ascinpt;
  //select.dataset.i = sInd;
  //sInd++;
  select.setAttribute("onchange", "onSelectChange(this)");
  for (; i < il; ++i)
    if (skippedIndexes.indexOf(i) == -1) {
      option = document.createElement('option');
      option.setAttribute('value', controls[i].value);
      option.appendChild(document.createTextNode(controls[i].text));
      select.appendChild(option);
    }
  html1.insertAdjacentHTML('beforeend', "<b>Tecla</b><br>");
  html1.appendChild(select);
  html1.insertAdjacentHTML('beforeend', "<br><b>Acción</b><br>");
  html1.appendChild(text);
  html.appendChild(html1);

  html.appendChild(delbtn);
  return html;
}
.sep {
  border-top: 4px dashed #A4A4A4;
  margin: 15px 0 15px 0;
}
<div>
  <input type="button" value="Añadir tecla" onclick="addControl(this.parentNode)" />
</div>

Ad
source: stackoverflow.com
Ad