-2

I have the following HTML

<div id="form">
        <div id="test">
            <textarea name="" placeholder="input_form" id="" cols="30" rows="10"></textarea>
        </div>
    </div>

and I am trying to build an form based on JSON data

for (i in response[key].request_fields) {
var values = ( () => {
    var out = "";
    for(var e in response[key].request_fields[i].values){
        out += "<li class='item_check'>" + 
                    "<input type='checkbox' id='" + response[key].request_fields[i].values[e] + "'>" +
                    "<label for='" + response[key].request_fields[i].values[e] + "'>" 
                        + response[key].request_fields[i].values[e] + 
                    "</label>" + 
                "</li>";
    }
    return out;
})();

document.getElementById("test").innerHTML += "<div class='form_section'>" + 
                                                "<label>" + response[key].request_fields[i].label + "</label>" + 
                                                "<ul>" + values + "</ul>" + 
                                             "</div>";  
}  

It's working properly, except that I need this result to be printed before my textarea. How can I prepend it ?

vbotio
  • 1,566
  • 3
  • 26
  • 53

2 Answers2

2

You can get the parentNode and use insertBefore function to insert new element

var parent = document.getElementById("test");
var txa = parent.querySelector('textarea');
var div = document.createElement('div');
div.class = 'form_section';
div.innerHTML = "<label>My label text</label>" + 
                "<ul><li>val1</li><li>val2</li></ul>";
parent.insertBefore(div, txa);
<div id="form">
  <div id="test">
    <textarea name="" placeholder="input_form" id="" cols="30" rows="10"></textarea>
  </div>
</div>
MaxZoom
  • 7,619
  • 5
  • 28
  • 44
  • not working. Uncaught TypeError: Failed to execute 'insertBefore' on 'Node': parameter 1 is not of type 'Node'. – vbotio Jun 07 '17 at 17:47
  • You need a real node, not a string. I have updated the answer with node building sample, where `innerHTML` would contain the string value. – MaxZoom Jun 07 '17 at 17:50
0

Here's how you can do this using proper DOM manipulation. Though it's a lot more verbose than your original code, it is a lot more resilient to arbitrary values containing special characters (like &, <, etc.) and doesn't rely on fragile string concatenation.

The main points are:

  • document.createElement to create elements
  • appendChild to append child elements
  • insertBefore to insert elements before another element

var response = getResponse();
var key = '_embedded';

function liItemForValue(value) {
  var li = document.createElement('li');
  li.classList.add('item_check');

  var checkbox = document.createElement('input');
  checkbox.type = 'checkbox';
  checkbox.id = value;

  var label = document.createElement('label');
  label.for = value;
  label.textContent = value;

  li.appendChild(checkbox);
  li.appendChild(label);

  return li;
}

function makeFormSection(rf) {
  var liItems = Object.keys(rf.values).map(function(key) {
    return liItemForValue(rf.values[key]);
  });

  var formSection = document.createElement('div');
  formSection.classList.add('form_section');

  var label = document.createElement('label');
  label.innerText = rf.label;

  var ul = document.createElement('ul');

  liItems.forEach(function(liItem) {
    ul.appendChild(liItem);
  });

  formSection.appendChild(label);
  formSection.appendChild(ul);

  return formSection;
}

var formSections = response[key].request_fields.map(makeFormSection);

var test = document.getElementById('test');
var textarea = test.querySelector('textarea');

formSections.forEach(function(formSection) {
  test.insertBefore(formSection, textarea);
});


function getResponse() {
  return {
    "_embedded": {
      "request_fields": [{
        "reference": null,
        "name": "Qual será o serviço?",
        "label": "Qual será o serviço?",
        "placeholder": "Qual será o serviço?",
        "values": {
          "Coloração": "Coloração",
          "Corte": "Corte",
          "Escova ": "Escova ",
          "Escova progressiva/definitiva": "Escova progressiva/definitiva",
          "Luzes": "Luzes"
        }
      }, {
        "reference": null,
        "name": "Para quem será o serviço?",
        "label": "Para quem será o serviço?",
        "placeholder": "Para quem será o serviço?",
        "values": {
          "Criança": "Criança",
          "Homem": "Homem",
          "Mulher": "Mulher"
        }
      }]
    }
  };
}
<div id="form">
  <div id="test">
    <textarea name="" placeholder="input_form" id="" cols="30" rows="10"></textarea>
  </div>
</div>
JLRishe
  • 99,490
  • 19
  • 131
  • 169