No se puede configurar innerHTML en tbody en IE

5 minutos de lectura

No se puede configurar innerHTML en tbody en IE
ensayador

Tengo una tabla como esta:

<table>
<thead>
    <tr>
        <th colspan="1">a</th>
        <th colspan="3">b</th>
    </tr>
</thead>
<tbody id="replaceMe">
    <tr>
        <td>data 1</td>
        <td>data 2</td>
        <td>data 3</td>
        <td>data 4</td>
    </tr>
</tbody>
</table>

y un método me devuelve lo siguiente después de una solicitud ajax:

<tr>
    <td>data 1 new</td>
    <td>data 2 new</td>
    <td>data 3 new</td>
    <td>data 4 new</td>
</tr>

Quiero cambiar el HTML interno como

document.getElementById('replaceMe').innerHTML = data.responseText;

Sin embargo, parece que IE no puede configurar innerHTML en <tbody>. ¿Alguien puede ayudarme con una solución simple para este problema?

  • además, usar una biblioteca como jQuery NO es una opción.

    – probador

    18 ene.

1642910706 453 No se puede configurar innerHTML en tbody en IE
Cicuta

Eso es cierto, innerHTML en tbody elementos es de solo lectura en IE

La propiedad es de lectura/escritura para todos los objetos excepto los siguientes, para los cuales es de solo lectura: COL, COLGROUP, FRAMESET, HEAD, HTML, STYLE, TABLE, TBODY, TFOOT, THEAD, TITLE, TR.

fuente: http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx

Puedes hacer algo como esto para evitarlo:

function setTBodyInnerHTML(tbody, html) {
  var temp = tbody.ownerDocument.createElement('div');
  temp.innerHTML = '<table>' + html + '</table>';

  tbody.parentNode.replaceChild(temp.firstChild.firstChild, tbody);
}

Básicamente, crea un nodo temporal en el que inyectas un table. Luego reemplaza el tbody con el tbody de lo inyectado table. Si resulta ser lento, puede hacerlo más rápido almacenando en caché temp en lugar de crearlo cada vez.

  • var myTableBody = document.getElementById(‘valor de su tbody Id’);setTBodyInnerHTML(myTableBody, “valor para agregar”);

    – Matoeil

    08 abr.


  • No tan bueno: el reemplazo pierde todos los atributos originales, como id=”replaceMe” en la pregunta.

    – Wolfgang Kuehn

    24 ene.

  • @NINtender input es una etiqueta de cierre automático, no tiene innerHTML.

    – malhumorado

    04 abr.

  • Simplemente no hay nada más tonto que esto

    – VH-NZZ

    28 mayo 2019 en 02:29

No se puede configurar innerHTML en tbody en IE
Juan Mendes

Cree un nodo temporal para almacenar una tabla, luego cópielos en el cuerpo

  var tempNode = document.createElement('div');
  tempNode.innerHTML = "<table>" + responseText+ "</table>";

  var tempTable = tempNode.firstChild;
  var tbody = // get a reference to the tbody
  for (var i=0, tr; tr = tempTable.rows[i]; i++) {
    tbody.appendChild(tr);
  } 

Ambas respuestas anteriores parecen un poco confusas. Además, el div creado nunca se elimina, por lo que llamar a esas funciones repetidamente consume memoria. Prueba esto:


// this function must come before calling it to properly set “temp” 
function MSIEsetTBodyInnerHTML(tbody, html) { //fix MS Internet Exploder’s lameness
  var temp = MSIEsetTBodyInnerHTML.temp;
  temp.innerHTML = '<table><tbody>' + html + '</tbody></table>';
  tbody.parentNode.replaceChild(temp.firstChild.firstChild, tbody);  }
MSIEsetTBodyInnerHTML.temp = document.createElement('div');

if (navigator  &&  navigator.userAgent.match( /MSIE/i ))  
  MSIEsetTBodyInnerHTML(tbody, html);
else  //by specs, you can not use “innerHTML” until after the page is fully loaded  
  tbody.innerHTML=html;    

Sin embargo, incluso con este código, MSIE no parece cambiar correctamente el tamaño de las celdas de la tabla en mi aplicación, pero estoy llenando una etiqueta tbody vacía con contenido generado variable, mientras que los valores colspan de las celdas principales se establecen en un valor fijo : el número máximo de celdas que puede haber en el cuerpo generado. Si bien el cuerpo de la tabla tiene 50 celdas de ancho, solo se muestran dos columnas. Tal vez si la tabla se llenara originalmente y las celdas se reemplazaran con la misma estructura interna, este método funcionaría. Chrome de Google hace un excelente trabajo al reconstruir la tabla, mientras que el navegador de escritorio de Opera puede cambiar el tamaño a más columnas sin problemas, pero si elimina columnas, los anchos de columna restantes permanecen tan estrechos como antes; sin embargo, con Opera, al ocultar la tabla (display=none) y luego volver a mostrarla (display=table), las celdas del cuerpo de la tabla generada se dimensionan correctamente. Me he dado por vencido con Firefox. Es el MSIE-6 de 2012: una pesadilla para desarrollar, para el cual se debe agregar un marcado adicional solo para que los diseños HTML-CSS funcionen porque no se ajusta a los estándares que incluso MSIE ahora hace. Así que no he probado el funcionamiento de tbody.innerHTML en Firefox.

  • El nodo obtiene basura recolectada después de que la función sale, ya que no está conectado al DOM.

    – Juan Mendes

    26 abr.

Esto se puede arreglar creando un shim/polyfill para .innerHTML. Esto podría ayudarlo (a usted, querido lector) a comenzar:

if (/(msie|trident)/i.test(navigator.userAgent)) {
 var innerhtml_get = Object.getOwnPropertyDescriptor(HTMLElement.prototype, "innerHTML").get
 var innerhtml_set = Object.getOwnPropertyDescriptor(HTMLElement.prototype, "innerHTML").set
 Object.defineProperty(HTMLElement.prototype, "innerHTML", {
  get: function () {return innerhtml_get.call (this)},
  set: function(new_html) {
   var childNodes = this.childNodes
   for (var curlen = childNodes.length, i = curlen; i > 0; i--) {
    this.removeChild (childNodes[0])
   }
   innerhtml_set.call (this, new_html)
  }
 })
}

var mydiv = document.createElement ('div')
mydiv.innerHTML = "test"
document.body.appendChild (mydiv)

document.body.innerHTML = ""
console.log (mydiv.innerHTML)

http://jsfiddle.net/DLLbc/9/

<table id="table">
<thead>
    <tr>
        <th colspan="1">a</th>
        <th colspan="3">b</th>
    </tr>
</thead>
<tbody id="replaceMe">
    <tr>
        <td>data 1</td>
        <td>data 2</td>
        <td>data 3</td>
        <td>data 4</td>
    </tr>
</tbody>
</table>
<button type="button" onclick="replaceTbody()">replaceTbody</button>
<script>
function $(id){ 
    return document.getElementById(id);
}

function replaceTbody(){
    var table = $('table');
    table.removeChild($('replaceMe'));
    var tbody = document.createElement("tbody");
    tbody.setAttribute("id","replaceMe");
    table.appendChild(tbody);

    var tr = document.createElement('tr');
    for(var i=1;i<5;i++){
        var td = document.createElement('td');
        td.innerHTML = 'newData' + i;
        tr.appendChild(td);
    }
    tbody.appendChild(tr);
}
</script>

  • ¿Podría agregar un breve resumen de la solución propuesta?

    – mrtig

    11 oct.

  • ¿Podría agregar un breve resumen de la solución propuesta?

    – mrtig

    11 oct.

.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad