Javascript: agregue HTML al elemento contenedor sin innerHTML

167

Necesito una forma de agregar HTML a un elemento contenedor sin usar innerHTML. La razón por la que no quiero usar innerHTML es porque cuando se usa así:

element.innerHTML += htmldata

Funciona reemplazando todo el html primero antes de agregar el viejo html más el nuevo html. Esto no es bueno porque restablece los medios dinámicos, como los videos flash incrustados ...

Podría hacerlo de esta manera, lo que funciona:

var e = document.createElement('span');
e.innerHTML = htmldata;
element.appendChild(e);

Sin embargo, el problema con esa forma es que ahora hay una etiqueta de extensión adicional en el documento que no quiero.

¿Cómo se puede hacer esto entonces? ¡Gracias!

Beto
fuente
1
¿Por qué no usar Jquery? Verifique mi respuesta detallada a continuación. stackoverflow.com/a/50482776/5320562
Loukan ElKadi

Respuestas:

102

Para dar una alternativa (ya que el uso DocumentFragmentno parece funcionar): puede simularlo iterando sobre los elementos secundarios del nodo recién generado y solo agregue esos.

var e = document.createElement('div');
e.innerHTML = htmldata;

while(e.firstChild) {
    element.appendChild(e.firstChild);
}
Felix Kling
fuente
2
Pensé que estábamos buscando una solución que no usa "innerHTML"
kennydelacruz
1
@kennydelacruz: El OP no quería agregar nuevo HTML a un HTML existente porque destruye y recrea los elementos existentes. El OP encontró una solución al crear un nuevo elemento y agregarlo, pero no quería agregar un elemento adicional. Acabo de ampliar esa solución para mostrar que pueden mover / agregar los elementos recién creados, que no afectan los elementos existentes.
Felix Kling el
Sé que esto es viejo, pero ¿alguien puede explicarme por qué uno puede iterar sobre e.firstChild?
Toastgeraet
1
@Toastgeraet: Este es ejemplo no es la iteración más e.firstChild . Más bien, verifica si etiene un hijo y, en caso afirmativo, mueva ese hijo al elemento.
Felix Kling
570

Me sorprende que ninguna de las respuestas mencionara el insertAdjacentHTML()método. Compruébalo aquí . El primer parámetro es donde desea que se anexe la cadena y tome ("beforebegin", "afterbegin", "beforeend", "afterend"). En la situación del OP, usarías "beforeend". El segundo parámetro es solo la cadena html.

Uso básico:

var d1 = document.getElementById('one');
d1.insertAdjacentHTML('beforeend', '<div id="two">two</div>');
alnafie
fuente
53
Acabo de probar su solución, así como la aceptada. Ambos funcionan, pero el tuyo es solo de 2 líneas y sin bucles. Suena como un ganador para mi.
Corwin01
3
Para referencia a cualquiera que pueda elegir esta ruta: este método no funciona bien con las tablas en IE9.
Corwin01
2
En Chrome me dice Uncaught TypeError: undefined is not a function!
J86
19
Esta joya escondida necesita más exposición.
Seth
Obtendrá un error si intenta utilizar este método en algo que no sea un Nodo, solo para su información.
Alex W
15

Alnafie tiene una gran respuesta para esta pregunta. Quería dar un ejemplo de su código de referencia:

var childNumber = 3;

function addChild() {
  var parent = document.getElementById('i-want-more-children');
  var newChild = '<p>Child ' + childNumber + '</p>';
  parent.insertAdjacentHTML('beforeend', newChild);
  childNumber++;
}
body {
  text-align: center;
}
button {
  background: rgba(7, 99, 53, .1);
  border: 3px solid rgba(7, 99, 53, 1);
  border-radius: 5px;
  color: rgba(7, 99, 53, 1);
  cursor: pointer;
  line-height: 40px;
  font-size: 30px;
  outline: none;
  padding: 0 20px;
  transition: all .3s;
}
button:hover {
  background: rgba(7, 99, 53, 1);
  color: rgba(255,255,255,1);
}
p {
  font-size: 20px;
  font-weight: bold;
}
<button type="button" onclick="addChild()">Append Child</button>
<div id="i-want-more-children">
  <p>Child 1</p>
  <p>Child 2</p>
</div>

Esperemos que esto sea útil para otros.

Trevor Nestman
fuente
2
Odio ser riguroso con las reglas, pero creo que hubiera sido mejor si creara una demostración (jsfiddle, codepen, etc.) y luego la agregara a la respuesta de Alnafie utilizando la función de edición o enviando un comentario. Crear una respuesta solo para demostrar la respuesta de otro usuario no es cómo funciona SO, independientemente de cuán útil sea la información que proporcionó. Imagínese si cada usuario decidiera demostrar otra respuesta creando una respuesta, se volvería complicado.
Martin James
2
<div id="Result">
</div>

<script>
for(var i=0; i<=10; i++){
var data = "<b>vijay</b>";
 document.getElementById('Result').innerHTML += data;
}
</script>

asigne los datos para div con el símbolo "+ =", puede agregar datos, incluidos datos html anteriores

vijay
fuente
11
La pregunta específicamente requiere no usar element.innerHTML += data.
musicnothing
1

Esto es para lo que DocumentFragmentestaba destinado.

var frag = document.createDocumentFragment();
var span = document.createElement("span");
span.innerHTML = htmldata;
for (var i = 0, ii = span.childNodes.length; i < ii; i++) {
    frag.appendChild(span.childNodes[i]);
}
element.appendChild(frag);

document.createDocumentFragment, .childNodes

Raynos
fuente
Acabo de probar esto y no funciona. ¿Es así como debería usarse?
Bob
¿De dónde vienes (a)? ¿Es eso un error tipográfico?
Ash Burlaczenko
1
Sí, eso es un error tipográfico, debería ser e. No creo que pueda usar innerHTML para un fragmento. Esto no está funcionando
Bob
@Bob He ido para la salida de la copia usando jQuery.
Raynos
jQuery no no! No voy a incluir jQuery solo para una pequeña función: \ Es simplemente exagerado
Bob
-1

Cómo pescar y al usar un código estricto. Hay dos funciones de requisitos previos necesarias en la parte inferior de esta publicación.

xml_add('before', id_('element_after'), '<span xmlns="http://www.w3.org/1999/xhtml">Some text.</span>');

xml_add('after', id_('element_before'), '<input type="text" xmlns="http://www.w3.org/1999/xhtml" />');

xml_add('inside', id_('element_parent'), '<input type="text" xmlns="http://www.w3.org/1999/xhtml" />');

Agregue varios elementos (el espacio de nombres solo debe estar en el elemento principal):

xml_add('inside', id_('element_parent'), '<div xmlns="http://www.w3.org/1999/xhtml"><input type="text" /><input type="button" /></div>');

Código dinámico reutilizable:

function id_(id) {return (document.getElementById(id)) ? document.getElementById(id) : false;}

function xml_add(pos, e, xml)
{
 e = (typeof e == 'string' && id_(e)) ? id_(e) : e;

 if (e.nodeName)
 {
  if (pos=='after') {e.parentNode.insertBefore(document.importNode(new DOMParser().parseFromString(xml,'application/xml').childNodes[0],true),e.nextSibling);}
  else if (pos=='before') {e.parentNode.insertBefore(document.importNode(new DOMParser().parseFromString(xml,'application/xml').childNodes[0],true),e);}
  else if (pos=='inside') {e.appendChild(document.importNode(new DOMParser().parseFromString(xml,'application/xml').childNodes[0],true));}
  else if (pos=='replace') {e.parentNode.replaceChild(document.importNode(new DOMParser().parseFromString(xml,'application/xml').childNodes[0],true),e);}
  //Add fragment and have it returned.
 }
}
Juan
fuente