CRUD em HTML com Javascript e jQuery

Como desenvolvedores, somos sempre convidados a fazer mais pelos nossos utilizadores. Eles querem que suas páginas sejam mais rápidas, mais leves e com mais funcionalidades. Isto significa que temos que trabalhar mais com JavaScript e jQuery no frontend. Fazendo isso, reduzimos o número de requisições ao servidor, e assim aumentamos a performance da página.

Logo jQuery

Neste artigo mostrarei como adicionar, editar e eliminar dados numa tabela HTML usando JavaScript e jQuery, mas sem fazer requisições ao servidor. No próximo artigo falarei em como pegar estes dados e usar Web API para recuperá-los e modificá-los.

Para demostrar os conceitos deste artigo, criarei uma página chamada MinhaEstante. Nesta página poderei listar todos os meus livros, e eventualmente, adicionar, editar e eliminar os mesmos. Usarei o Bootstrap de forma a conseguirmos uma aparência mais amigável, mas o seu uso não é obrigatório.

Adicionar um Livro

O código da página usado para ilustrar este conceito pode ser encontrado no GitHub. O código abaixo cria uma tabela vazia com uma tag <thead> para o cabeçalho de cada coluna na tabela. Existem três colunas: Título do Livro, Nome do Autor e a Editora. Perceba que não temos a tag <tbody> nesta tabela. Deixei de fora com o propósito de ilustrar como verificar isso usando o jQuery, e caso necessário, como adicioná-la.

<div class="container">
  <div class="row">
    <div class="col-md-6">
      <h2>Meus Livros</h2>
    </div><!--// .col-md-6 -->
  </div><!--// .row -->

  <div class="row">
    <div class="col-md-6">
      <table id="bookTable" class="table table-bordered table-condensed table-striped">
        <thead>
          <tr>
            <th>Título do Livro</th>
            <th>Autor</th>
            <th>Editora</th>
          </tr>
        </thead>
      </table>
    </div><!--// .col-md-6 -->
  </div><!--// .row -->
</div><!--// .container -->

 

Adicionar as linhas de cada produto na tabela

No fim da página criei uma tag <script> com uma função chamada booksAdd(). Esta função usa o método append() para adicionar a tag <tr> com  respectivas tags <td> de forma a criar uma linha para a nossa tabela. Usei um selector jQuery para localizar o atributo ID da tabela e a tag <tbody>, e adicionar dentro dela as tags <tr> e <td> usando o append() como mostra o código abaixo:

<script type="text/javascript">
  function booksAdd(){
    // Adiciona um livro na tabela
    $("#bookTable tbody").append(
      "<tr>" +
        "<td>Test-Driven Development - Teste e Design no Mundo Real com .NET</td>" +
        "<td>Mauricio Aniche</td>" +
        "<td>Casa do Código</td>" +
      "</tr>"
    );
  }
</script>

O código mostrado anteriormente para a criação da tabela, não inclui a tag <tbody> dentro da tabela. Se rodarmos o nosso código (no navegador) agora, nenhuma linha será adicionada à tabela porque o selector $(“bookTable tbody”) retorna null como resultado. Sendo assim, é importante que se tenha a tag <tbody>. Mas como não a temos, podemos adicioná-la programaticamente.

<script type="text/javascript">
  function booksAdd(){
    // Primeiro verifica se a tag <tbody> existe. Se não, adiciona uma
    if ($("#bookTable tbody").length == 0){
      $("#bookTable").append("<tbody></tbody>");
    }

    // ...
  }
</script>

No código acima, verificamos antes se existe a tag <tbody> dentro da nossa tabela. Caso exista, continuamos com a adição da linha, caso contrário adicionamos antes a tag <tbody>.

Agora podemos chamar a nossa função quando o documento é carregado adicionando a função do jQuery “document.ready” logo antes da tag de fechamento </script>, como mostra o código abaixo:

<script type="text/javascript">
  function booksAdd(){
    // ...
  }

  $(document).ready(function(){
   booksAdd();
  });
</script>

Feito isso, a seguinte tabela será mostrada na nossa página:

Meus Livros

Adicionando Linhas dinamicamente

Vamos tornar nossa página um pouco mais dinâmica, obtendo os dados do livro a partir de um formulário preenchido pelo utilizador e adicioná-los na tabela. Vamos adicionar três campos para o utilizador submeter os dados que serão inseridos na tabela. O utilizador informa o Título do Livro, o Nome do Autor e o Nome da Editora, como mostra a imagem abaixo.

Captura de ecrã 2016-03-30, às 21.49.51

Depois do utilizador preencher o formulário, estes dados são submetidos e adicionados na tabela HTML.

Além dos campos de texto tem um botão (<button>) que quando clicado, submete os dados inseridos na tabela. É um botão HTML normal com a chamada de uma função (bookUpdate) no evento onclick.

<button type="button" id="updateButton" onclick="bookUpdate();" class="btn btn-lg btn-primary">
  Adicionar Livro
</button>

Adicionar uma linha a partir do formulário

Uma vez que o utilizador preencha o formulário, ele clica no botão “Adicionar Livro”. Como resposta a este evento clique, a função bookUpdate() é chamada como mostra o trecho de código abaixo.

function bookUpdate(){
  if ($("#book_title").val() != null && $("#book_title").val() != ''){
    // Adiciona o Livro na Tabela
    bookAddToTable();

    // Limpa o formulário
    formClear();

    // Mantém o foco no campo Título
    $("#book_title").focus();
  }
}

Caso o campo book_title (título do livro) seja preenchido, então a função bookAddToTable é chamada para construir a nova linha para a tabela. Em seguida, chama a função formClear() para limpar o formulário e prepará-lo para o próximo registo a ser adicionado. Finalmente, o campo Título do Livro recebe o foco.

A função bookAddToTable() apresentada no trecho abaixo, é idêntico ao código da função booksAdd(). A diferença está no facto de que a função bookAddToTable() usa o jQuery para recuperar os valores a serem inseridos a partir das caixas de texto do formulário e constroi os elementos <td> a partir destes valores.

function bookAddToTable(){
  // Primeiro verifica se a tag <tbody> existe. Adiciona um caso não exista
  if ($("#bookTable tbody").length == 0){
    $("#bookTable").append("<tbody></tbody>");
  }

  // Adiciona Livro na Tabela
  $("#bookTable tbody").append(
    "<tr>" +
      "<td>" + $("#book_title").val() + "</td>" +
      "<td>" + $("#book_author").val() + "</td>" +
      "<td>" + $("#book_publisher").val() + "</td>" +
    "</tr>"
  );
}

A função formClear() usa o selector jQuery para encontrar cada campo do formulário e definir como valor dos mesmos uma string vazia. Definindo o valor como vazio limpa os campos de texto, assim o utilizador pode inserir novos valores sem a necessidade de limpar antes o formulário manualmente.

function formClear(){
  $("#book_title").val("");
  $("#book_author").val("");
  $("#book_publisher").val("");
}

Eliminar um Livro

Depois de adicionarmos alguns livros, com certeza que em algum momento precisaremos eliminar um ou mais livros previamente adicionados. Vamos então adicionar um botão Eliminar para cada linha da nossa tabela, como mostra o trecho de código abaixo. Iremos modificar o elemento <thead> adicionando um novo elemento <th> com a palavra Eliminar.

<thead>
  <tr>
    <th>Título do Livro</th>
    <th>Autor</th>
    <th>Editora</th>
    <th>Eliminar</th>
  </tr>
</thead>

Adicionar um Botão Eliminar para cada linha

Vamos modificar a função bookAddToTable() para incluir um botão cada vez que uma nova linha for inserida. No JavaScript que escrevemos para criar os elementos <tr> e <td>, vamos adicionar mais um elemento <td> que inclui a definição do botão (<button>). Este botão usa uma classe do Bootstrap para dar-lhe estilo e um glyphicon do Bootstrap para mostrar um “X” para simbolizar a função eliminar. O botão também precisa de um evento onclick para chamar a função bookDelete(). A esta função, passamos a palavra reservada this que referencia o próprio botão.

function bookAddToTable(){
  // Primeiro verifica se a tag <tbody> existe. Adiciona um caso não exista
  if ($("#bookTable tbody").length == 0){
    $("#bookTable").append("<tbody></tbody>");
  }

  // Adiciona Livro na Tabela
  $("#bookTable tbody").append(
    "<tr>" +
      "<td>" + $("#book_title").val() + "</td>" +
      "<td>" + $("#book_author").val() + "</td>" +
      "<td>" + $("#book_publisher").val() + "</td>" +
      "<td>" +
        "<button type='button' " +
          "onclick='bookDelete(this);' " +
          "class='btn btn-default'>" +
          "<span class='glyphicon glyphicon-remove'></span>" +
        "</button>" +
      "</td>" +
    "</tr>"
  );
}

Eliminar a Linha

A função bookDelete() recebe como parâmetro a referência do botão Eliminar. A partir deste botão, podemos usar a função parents() do jQuery para encontrar a tag <tr> onde se encontra o botão. Uma vez localizada a tag <tr>, usamos a função remove() para eliminar esta linha da tabela, como mostra o código abaixo:

function bookDelete(button_delete){
  $(button_delete).parents("tr").remove();
}

Editar um Livro

Vimos como adicionar e como eliminar linhas em uma tabela HTML. Agora vamos nos focar em como editar estas linhas. Tal como adicionamos o botão Eliminar para cada linha da nossa tabela, vamos também adicionar um botão Editar. Novamente, precisamos modificar o elemento <thead> adicionando um novo elemento <th> com a palavra Editar, como mostra o código abaixo.

<thead>
  <tr>
    <th>Título do Livro</th>
    <th>Autor</th>
    <th>Editora</th>
    <th>Editar</th>
    <th>Eliminar</th>
  </tr>
</thead>

Adicionando uma linha com um botão Editar

Do mesmo jeito que construímos em JavaScript o botão para eliminar uma linha, também vamos construir para Editar. O evento onclick chama a função bookDisplay() que recebe a palavra-chave this como parâmetro para referenciar o próprio botão e assim recuperar dados da linha onde está localizado o botão.

function bookAddToTable(){
  // Primeiro verifica se a tag <tbody> existe. Adiciona um caso não exista
  if ($("#bookTable tbody").length == 0){
    $("#bookTable").append("<tbody></tbody>");
  }

  // Adiciona Livro na Tabela
  $("#bookTable tbody").append(
    "<tr>" +
      "<td>" + $("#book_title").val() + "</td>" +
      "<td>" + $("#book_author").val() + "</td>" +
      "<td>" + $("#book_publisher").val() + "</td>" +
      "<td>" +
        "<button type='button' " +
          "onclick='bookDisplay(this);' " +
          "class='btn btn-default'>" +
          "<span class='glyphicon glyphicon-edit'></span>" +
        "</button>" +
      "</td>" +
      "<td>" +
        "<button type='button' " +
          "onclick='bookDelete(this);' " +
          "class='btn btn-default'>" +
          "<span class='glyphicon glyphicon-remove'></span>" +
        "</button>" +
      "</td>" +
    "</tr>"
  );
}

Mostrando dados nos campos de texto

Quando o utilizador clicar no botão Editar, armazenamos o linha actual da tabela numa variável global. Vamos definir a variável chamada _row logo após a apertura da <script>, fora de qualquer função, assim a mesma estará visível para qualquer função dentro da página.

<script>
  // Linha actual que está sendo editada
  var _row = null;
  //...
</script>

Na função bookAddToTable(), passamos o parâmetro this na função bookDisplay() chamado no evento onclick do botão Editar. Este this referência o botão Editar. Vamos escrever a função bookDisplay() para encontrar a linha actual a partir da tag <tr> onde se encontra o botão Editar.

function bookDisplay(button_edit){
  _row = $(button_edit).parents("tr");
  var cols = _row.children("td");

  $("#book_title").val($(cols[0]).text());
  $("#book_author").val($(cols[1]).text());
  $("#book_publisher").val($(cols[2]).text());

  // Mudar o texto do Botão
  $("#updateButton").text("Actualizar");
}

No código acima, recuperamos todas as colunas <td> num array a partir da linha actual usando a função children() da variável _row.

Usamos a função val() para passar os dados de cada coluna no formulário. E finalmente, mudamos o texto do botão “Adicionar Livro” para “Actualizar” uma vez que estamos a editar o livro.

Actualizando os dados

Quando o utilizador clicar no botão updateButton, a função bookUpdate() é chamada. O texto encontrado no botão irá determinar a acção a ser executada pela função bookUpdate(). Lembre-se, quando clicamos no botão Editar, o texto do botão updateButton muda para “Actualizar“. Vamos agora actualizar o código da função bookUpdate() para verificar o texto do botão updateButton e executar a função correcta.

function bookUpdate(){
  if ($("#book_title").val() != null && $("#book_title").val() != ''){
    if ($("#updateButton").text() == "Actualizar"){
      bookUpdateInTable();
  } else {
    // Adiciona o Livro na Tabela
    bookAddToTable();
  }

  // Limpa o formulário
  formClear();

  // Mantém o foco no campo Título
  $("#book_title").focus();
}

Existem diferentes formas de actualizarmos um livro. Já temos a linha armazenada na variável _row, logo podemos nos referenciar a cada célula individualmente nesta linha e actualizar cada célula da tabela usando a função val() de cada campo de texto. Outra forma é adicionarmos os dados actualizados imediatamente após a linha actual, em seguida eliminar a linha actual da tabela. Iremos usar esta última opção, uma vez que ela nos permite reutilizar a função bookBuildTableRow(). Por último, vamos limpar o formulário e mudar o texto do botão para “Adicionar Livro”.

function bookUpdateInTable(){
  // Adiciona a linha modifica na tabela
  $(_row).after(bookBuildTableRow());

  // Remover a linha antiga
  $(_row).remove();

  // Limpar o formulário
  formClear();

  // Mudar o texto do Botão
  $("#updateButton").text("Adicionar Livro");
}

Usando os atributos data-*

Neste artigo, nos focamos apenas em trabalhar com código frontend. Em algum momento, precisaremos enviar de volta os dados para o servidor e também recuperar os mesmos dados a partir do servidor. A maioria atribui uma chave primária (id único) a cada linha da tabela. Vamos agora modificar a nossa página para usar os atributos data-* para manter o registo das chave primárias nas linhas da tabela.

Adicionando duas variáveis

Precisamos criar duas novas variáveis globais: _nextId e _activeId. Estas variáveis são usadas para manter o registo o próximo ID a ser atribuído na nova linha e para manter o registo do ID da linha que está sendo editada.

<script type="text/javascript">
  // Próximo ID para adicionar um novo livro
  var _nextId = 1;

  // ID do livro que está sendo editado
  var _activeId = 0;

  // ...
</script>

Vamos eliminar a variável _row anteriormente criada, uma vez que estaremos usando estas variáveis ID para manter o registo de qual linha está sendo adicionada ou editada.

Estas duas novas variáveis são usadas para construirmos a linha a ser adicionada ou actualizada na nossa tabela. Vamos modificar a função bookBuildTableRow() para aceitar o parâmetro id para onde passaremos uma das duas variáveis. Este número único é adicionado no atributo data-* em ambos os botões Editar e Eliminar.

function bookBuildTableRow(id){
  var row = "<tr>" +
    "<td>" + $("#book_title").val() + "</td>" +
    "<td>" + $("#book_author").val() + "</td>" +
    "<td>" + $("#book_publisher").val() + "</td>" +
    "<td>" +
      "<button type='button' " +
        "onclick='bookDisplay(this);' " +
        "class='btn btn-default'" +
        "data-id='" + id + "'>" +
        "<span class='glyphicon glyphicon-edit'></span>" +
      "</button>" +
    "</td>" +
    "<td>" +
      "<button type='button' " +
        "onclick='bookDelete(this);' " +
        "class='btn btn-default'" +
        "data-id='" + id + "'>" +
        "<span class='glyphicon glyphicon-remove'></span>" +
      "</button>" +
    "</td>" +
  "</tr>"

  return row;
}

Obter o ID actual

Quando o utilizador clica no botão Editar, a função bookDisplay() é chamada. Extraímos o ID único do atributo data-id e o atribuímos à variável _activeId.

function bookDisplay(button_edit){
  var row = $(button_edit).parents("tr");
  var cols = row.children("td");

  _activeId = $($(cols[3]).children("button")[0]).data("id");

  $("#book_title").val($(cols[0]).text());
  $("#book_author").val($(cols[1]).text());
  $("#book_publisher").val($(cols[2]).text());

  // Mudar o texto do Botão
  $("#updateButton").text("Actualizar");
}

A função do jQuery .data() é passada como sufixo do atributo data- para recuperar o ID. Como usamos o data-id como a chave do nosso atributo data-, simplesmente passamos id na função .data() e este retorna o valor atribuído à este atributo.

Actualizar uma linha

Quando o utilizador clica no botão updateButton, a função bookUpdate() continua sendo chamada. Porém, precisamos modificar esta função para usar a variável _activeId e passar este valor na função bookUpdateInTable().

 

function bookUpdate(){
  if ($("#book_title").val() != null && $("#book_title").val() != ''){
    if ($("#updateButton").text() == "Actualizar"){
      bookUpdateInTable(_activeId);
    } else {
      // Adiciona o Livro na Tabela
      bookAddToTable();
    }

    // Limpa o formulário
    formClear();

    // Mantém o focu no campo Título
    $("#book_title").focus();
  }
}

Vamos também actualizar a função bookUpdateInTable() para encontrar a linha que contém este único ID. Esta função usa este ID para localizar o botão que contém o atributo data-* dentro da tabela.

function bookUpdateInTable(id){
  // Encontra o livro na tabela
  var row = $("#bookTable button[data-id='" + id + "']").parents("tr")[0];

  // Adiciona a linha modifica na tabela
  $(row).after(bookBuildTableRow());

  // Remover a linha antiga
  $(row).remove();

  // ...
}

O selector jQuery usa o parametro ID passado na função bookUpdateInTable(). Este selector retorna a única linha da tabela que está sendo editado. Uma vez localizada, substituímos esta linha na tabela com os dados que o utilizador inseriu a partir do formulário.

Adicionando uma nova linha

Toda vez que adicionarmos uma nova linha na tabela, atribuímos o valor da variável _nextId ao atributo data-* para a nova linha. Vamos modificar a função bookAddToTable() como mostra o código abaixo.

 

function bookAddToTable(){
  // Primeiro verifica se a tag <tbody> existe. Adiciona um caso não exista
  if ($("#bookTable tbody").length == 0){
    $("#bookTable").append("<tbody></tbody>");
  }

  // Adiciona Livro na Tabela
  $("#bookTable tbody").append(bookBuildTableRow(_nextId));

  // Incrementamos o nextId
  _nextId += 1;
}

Perceba como passamos a variável _nextId para a função bookBuildTableRow(). Depois deste novo livro ser criado, incrementamos o _nextId para que o próximo livro tenha um ID único.

Resultado Final:

Resultado Final

Conclusão

Neste artigo, vimos como Adicionar, Editar e Eliminar linhas na tabela HTML usando JavaScript e jQuery. Com estes conhecimentos tornamos a nossa página mais responsiva e preparamo-nos para o próximo passo, que é usar uma API para enviar os dados modificados de volta ao servidor, assunto este que abordaremos no próximo artigo.

O melhor destas técnicas é que não precisamos reenviar de volta para o servidor a página completa e não precisamos recarregar a página completa para recuperar os registos modificados. Assim, economizamos tempo e transferimos menos dados pela Internet. Isto é muito importante em dispositivos móveis que podem não estarem conectados à rede WiFi.

O código completo pode ser encontrado aqui: https://github.com/psantos10/minha_estante_artigo

,,,,