Tengo la siguiente configuración. Aquí estoy tratando de agregar radio personalizada y casillas de verificación.

Array.from(document.querySelectorAll("tr")).forEach((tr,index)=>{
  var mark=document.createElement("span");
  Array.from(tr.querySelectorAll("input")).forEach((inp,index1)=>{
    if(inp.type=="radio"){
      mark.classList.add("dotmark");
      inp.parentNode.appendChild(mark);
    }
    else{
      mark.classList.add("checkmark");
      inp.parentNode.appendChild(mark);//instead append in to the next td's label tag
    }
  })
})
span{
width:20px;
height:20px;
background:#ccc;
display:inline-block;
}
<table id="tab1" class="table labelCustom">
   <tbody>
        <tr><td><input type='radio' id='one' name='name'></td><td><label for='one'>example</label></td></tr>
        <tr><td><input type='radio' id='two' name='name'></td><td><label for='two'>example</label></td></tr>
        <tr><td><input type='radio' id='three' name='name'></td><td><label for='three'>example</label></td></tr>
   </tbody>
</table>

Quiero que el elemento span creado dinámicamente se inserte en la etiqueta. ahora lo está insertando en las entradas td.

Nota: la clase del elemento span depende del tipo de entrada.

0
Kaleem Nalband 10 sep. 2018 a las 15:21

3 respuestas

La mejor respuesta

Un enfoque, entre muchos, es el siguiente:

Array.from(document.querySelectorAll("tr")).forEach((tr, index) => {
  var mark = document.createElement("span");
  Array.from(tr.querySelectorAll("input")).forEach((inp, index1) => {

    // caching the <label> element for readability:
    let label = inp.parentNode.nextElementSibling.querySelector('label');

    // adding the class-name based on the result of the ternary operator,
    // if the input.type is equal to 'radio' we return the class-name of
    // 'dotmark', otherwise we return 'checkmark':
    mark.classList.add(inp.type === 'radio' ? 'dotmark' : 'checkmark');

    // appending the element held within the 'mark' variable:
    label.appendChild(mark);
  })
})
span {
  width: 20px;
  height: 20px;
  background: #ccc;
  display: inline-block;
}

span.dotmark {
  background-color: limegreen;
}

span.checkmark {
  background-color: #f90;
}
<table id="tab1" class="table labelCustom">
  <tbody>
    <tr>
      <td><input type='radio' id='one' name='name'></td>
      <td><label for='one'>example</label></td>
    </tr>
    <tr>
      <td><input type='radio' id='two' name='name'></td>
      <td><label for='two'>example</label></td>
    </tr>
    <tr>
      <td><input type='radio' id='three' name='name'></td>
      <td><label for='three'>example</label></td>
    </tr>
    <tr>
      <td><input type='checkbox' id='four' name='differentName'></td>
      <td><label for='four'>example</label></td>
    </tr>
  </tbody>
</table>

Como una adición, del comentario del OP a la pregunta:

Intenté nextSibling pero no funcionó pero nextSiblingElement funcionó.

La diferencia entre los dos es que nextSibling devuelve cualquier hermano, ya sea un nodo de texto, un nodo de elemento o cualquier otro, mientras que nextElementSibling, como su nombre lo indica, devuelve el siguiente hermano que también es un elemento-nodo.

Referencias:

1
David says reinstate Monica 10 sep. 2018 a las 12:38

No necesita bucles anidados, una vez en tr y luego en la entrada, ya que solo tiene una entrada y una etiqueta dentro de cada tr, por lo que puede combinarlos en una sola consulta como tr input. Y no necesita utilizar Array.from, ya que querySelectorAll devuelve NodeList que ya tiene una función forEach.

document.querySelectorAll('tr input').forEach(input => {
    const span = document.createElement('span')
    span.classList.add(input.type === 'radio' ? 'dotmark' : 'checkmark')
    input.parentNode.nextElementSibling.appendChild(span)
})
0
rmn 10 sep. 2018 a las 13:06

Uso

inp.parentNode.nextElementSibling.querySelector('label')

En lugar de solo

inp.parentNode
Array.from(document.querySelectorAll("tr")).forEach((tr,index)=>{
  var mark=document.createElement("span");
  Array.from(tr.querySelectorAll("input")).forEach((inp,index1)=>{
    if(inp.type=="radio"){
      mark.classList.add("dotmark");
      inp.parentNode.nextElementSibling.querySelector('label').appendChild(mark);
    }
    else{
      mark.classList.add("checkmark");
      inp.parentNode.nextElementSibling.querySelector('label').appendChild(mark);
    }
  })
})
span{
width:20px;
height:20px;
background:#ccc;
display:inline-block;
}
<table id="tab1" class="table labelCustom">
   <tbody>
        <tr><td><input type='radio' id='one' name='name'></td><td><label for='one'>example</label></td></tr>
        <tr><td><input type='radio' id='two' name='name'></td><td><label for='two'>example</label></td></tr>
        <tr><td><input type='radio' id='three' name='name'></td><td><label for='three'>example</label></td></tr>
   </tbody>
</table>
1
connexo 10 sep. 2018 a las 12:28