Dynamic table with addition of rows and columns

Asked

Viewed 2,922 times

2

Is it possible to create a dynamic table with the addition of rows and columns? According to the picture, the situation is: - Starts a table with 3 columns and a row; - Whereas the first line and the first column would have to be editable (it would be possible for the user to type in it); - Inside the empty lines would bring radio button;

Now comes the part where I can’t find a solution: - When you click the button + from the horizontal you will add one more column( maximum 5 columns); - When you click the + button from the vertical you will add one more line; - And they need to always be hitting the column with the lines, as shown in the image.

It is possible to make such a dynamic table? inserir a descrição da imagem aqui

3 answers

5


You will have some challenges to solve, such as correctly identifying the "radio Buttons" for each question, but I leave a code for suggestion.

//Adiciona linhas
$(".add-row").click(function () {
    if ($('.row-title').val() == '') {
        alert('Digite o título da pergunta');
        return;
    }

    if ($("#pergunta tbody tr td").length) {
        //clona a última linha
        $tr = $("#pergunta tbody tr:last-child").clone(true);
        var index = $("#pergunta tbody tr").length;
        var name = 'rd[' + (index + 1) + ']';
        //altera o nome e a propriedade checked do input
        $tr.find('td').children('input').attr('name', name).prop('checked', false);
        //altera o texto da primeira célula com o valor do input
        $tr.children('td:first-child').text($('.row-title').val());
        //adiciona no corpo da tabela
        $("#pergunta tbody").append($tr);
    } else {
        $("#pergunta tbody tr").append('<td>' + $('.row-title').val() + '</td>');
    }

});
//Adiciona colunas
$(".add-col").click(function () {

    if ($("#pergunta tbody tr td").length) {

        if ($('.col-title').val() == '') {
            alert('Digite a resposta');
            return;
        }

        var qtdMax = 5;//quantidade máxima de colunas
        if ($("#pergunta thead tr th").length < qtdMax) {
            //adiciona nova coluna com o texto do input
            $("#pergunta thead tr").append('<th>' + $('.col-title').val() + '</th>');
            //percorre cada linha do corpo da tabela
            $("#pergunta tbody tr").each(function () {
                //verifica o nome dos inputs da linha correspondente
                var name = 'rd[' + ($(this).index() + 1) + ']';
                //adiciona o input na coluna
                $(this).append('<td><input type="radio" name="' + name + '"></td>');
            });
        }
    } else {
        alert('Adicione a primeira pergunta antes de adicionar respostas!');
    }


});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table border="1" id="pergunta">
    <thead>
        <tr>
            <th></th>
        </tr>
    </thead>
    <tbody>
        <tr>

        </tr>
    </tbody>
</table>
<div>

</div>
<p>
    <input type="text" class="row-title" />
    <button type="button" class="add-row">
        + Pergunta
    </button>
</p>
<p>
    <input type="text" class="col-title" />
    <button type="button" class="add-col">
        + Resposta
    </button>

</p>

  • I did not understand the vote against, it would be important the feedback of the pq to negative the answer, so maybe it could improve it.

  • Sorry I didn’t inform you before, I only gave the negative point because I didn’t follow the maximum of 5 columns quoted above, and of course this point can be reversed.

  • @Mateusveloso ok I understand, I did the code in the rush and I didn’t notice, but I’ve corrected

  • @abfurlan your example is great, I’ll work on it, a question, in your example I can only select a radio, this must be what you talked about the challenge of identifying a radio for each question, you have some suggestion of the way to it?

  • @Isabellameirelles yes is one of the challenges, the name of the inputs were identical and so could only select one, see my edition with an idea of how to solve this problem.

  • 1

    @abfurlan Thank you so much for your help!!!

  • @Can I ask another question? If I wanted to remove the line that corresponds to: "answer" and the two radiosbuttons (which is the line that already comes in html, and leave it to be only for this addition to be done via the inputs (as already occurs in the next created lines), would I change all the logic applied in js? I tried to make a change to it but always disfigure the whole table

  • @Isabellameirelles yes, in this case changes the logic, will have to do some checks, but I believe that the easiest will be to create the table from scratch when there is no question yet. As soon as I get a break I’ll see if I can edit.

  • @abfurlan thank you, I’m trying to change but still unsuccessful, I feel like a lot

  • 1

    @Isabellameirelles see my edition, I believe it’s now ok

  • 1

    @abfurlan solved yes!!! thank you for your great help!!!

Show 6 more comments

3

First piece of advice I give you if you really need something so dynamic, jQUery is not the way, try the VueJS.

Below follows a complete example, see that manipulating the table is not so painful.

var app = new Vue({
  el: '#tabela',
  data: {
    respostas: [ 
      { texto: 'Sim' }, 
      { texto: 'Não' } 
    ],
    perguntas: [
      { 
        texto: 'Pergunta 1', 
        respostas: [ 
          { selecionado: false }, 
          { selecionado: false } 
        ] 
      }
    ]
  },
  methods: {
    addResposta: function (event) {
      var count = this.respostas.length + 1;
      if (count <= 5) {
        this.respostas.push({ texto: 'Resposta ' + count });
        this.perguntas.forEach(function (pergunta) {
          pergunta.respostas.push({ selecionado: false });
        })
      } else {
        alert('Não é possivel adicionar mais que 5 perguntas');
      }
    },
    delResposta: function (indice) {
      this.respostas.splice(indice, 1);
      this.perguntas.forEach(function (pergunta) {
        pergunta.respostas.splice(indice, 1);
      })
    },
    addPergunta: function (event) {
      var count = this.perguntas.length + 1;
      var respostas = this.respostas.map(function () {
        return { selecionado: false };
      })
      this.perguntas.push({ 
        texto: 'Pergunta ' + count,
        respostas: respostas
      });
    },
    delPergunta: function (indice) {
      this.perguntas.splice(indice, 1);
    }
  }
})
.resposta {
  white-space: nowrap;
}
.resposta input[type='text'] {
  width: 75px;
}

.pergunta {
  width: 150px;
}

.padrao {
  width: 75px;
}

input {
  box-sizing: border-box;
}

input[type='radio'] {
  text-align: center;
  width: 75px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.js"></script>
<table id="tabela">
  <thead>
    <tr>
      <th></th>
      <th v-bind:colspan="respostas.length">Respostas</th>
      <th></th>
    </tr>
    <tr>
      <th>Perguntas</th>
      <th v-for="(resposta, indice) in respostas" class="resposta">
        <input type="text" class="resposta" v-model="resposta.texto" />
        <input type="button" value="X" v-on:click="delResposta(indice)" />
      </th>
      <th>
        <input type="button" class="padrao" value="Adicionar" v-on:click="addResposta" />
      </th>
    </tr>
  </thead>
  <tbody>
    <tr v-for="(pergunta, indice) in perguntas">
      <td>
        <input type="text" class="pergunta" v-model="pergunta.texto" />
      </td>
      <td v-for="resposta in pergunta.respostas">
        <input type="radio" v-bind:name="'resposta' + indice" class="resposta" v-model="resposta.selecionado" />
      </td>
      <td>
        <input type="button" class="padrao" value="Remover" v-on:click="delPergunta(indice)" />
      </td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <td>
        <input type="button" class="pergunta" value="Adicionar Pergunta" v-on:click="addPergunta" />
      </td>
      <th v-bind:colspan="respostas.length"></th>
      <td>
        <input type="button" class="padrao" value="Salvar" />
      </td>
    </tr>
  </tfoot>
</table>

  • wow, this example is amazing, unfortunately I am still beginner and I have not had contact with vueJS, but I will definitely try to understand this example and who knows how to apply. Thank you!!!

2

function myFunction() {
    var table = document.getElementById("myTable");
    var row = table.insertRow(0);
    var cell1 = row.insertCell(0);
    var cell2 = row.insertCell(1);
    cell1.innerHTML = "NEW CELL1";
    cell2.innerHTML = "<input type='text' >";
}
<table id="myTable">
  <tr>
    <td>Row1 cell1</td>
    <td>Row1 cell2</td>
  </tr>
  <tr>
    <td>Row2 cell1</td>
    <td>Row2 cell2</td>
  </tr>
  <tr>
    <td>Row3 cell1</td>
    <td>Row3 cell2</td>
  </tr>
</table>
<br>

<button onclick="myFunction()">Try it</button>

Hello I believe this is the way to what you search, a button and your table goes automatically by clicking the button being changed.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.