David Gutierrez Marin
David Gutierrez Marin

Reputation: 25

hide and show error with jquery

I have 3 selects two hidden and one visible when I select the first option appears when you press one and the other the second option. All this in a table and use jquery to create a new row button in manipulacion.js file a counter and I have added it to the id of each select to not just call. the error is when I create a new row and not change me, I open the console and do not check any error. here I attached my codes in html and. js can copy it for them to discover that I'm wrong.

code html

<html>
<head>
</head>
<body>
<script type="text/javascript" src="jss/jquery-1.9.0.min.js"></script>
    <script type="text/javascript" src="manipulacion.js"></script>
<script>    
    $(document).ready(function () {
        $("#estado").change(function () {
            if ($("#estado").val() == 2) {
                $("#sino").show();
                $("#sexo").hide();            
            }
            if ($("#estado").val() == 3) {
                $("#sino").hide();
                $("#sexo").show();
            }
            });
            });
    </script>
    <table>
    <tr>
    <td>
    <select id="estado">
    <option value="1">Seleccione 1 opcion</option>
    <option value="2">Laboratorio</option>
    <option value="3">Datos Generales</option>
    </select>
    </td>
    <td>
    <!-- //laboratorio -->
    <select name="sino" id="sino"style="display:none">
    <option value="1">Si </option>
    <option value="2">No</option>
    </select>
    </td>
    <td>
    <!-- //datos generales -->
    <select name="sexo" id="sexo"  style="display:none">
    <option value="1">Masculino </option>
    <option value="2">Femenino</option>
    </select>
    </td>
    <td><input type="button" value="+" class="clsAgregarFila"></td>
    </tr>
    </table>
    </body>
    </html>

code manipulacion.js

//manipulacion 
var contLin=1
    $(document).ready(function () {
        $("#estado"+contLin).change(function () {      
            if ($("#estado"+contLin).val() == 2) {
                $("#sino"+contLin).show();
                $("#sexo"+contLin).hide();       
            }
            if ($("#estado"+contLin).val() == 3) {
                $("#sino"+contLin).hide();
                $("#sexo"+contLin).show();
            }
}           );



});


$(document).ready(function(){
    //evento que se dispara al hacer clic en el boton para agregar una nueva fila
    $(document).on('click','.clsAgregarFila',function(){
        //almacenamos en una variable todo el contenido de la nueva fila que deseamos
        //agregar. pueden incluirse id's, nombres y cualquier tag... sigue siendo html

        var strNueva_Fila='<tr>'+
'<td><select id="estado'+contLin+'"><option value="1">Seleccione 1 opcion</option><option value="2">Laboratorio</option><option value="3">Datos Generales</option></select></td>' +
'<td><select name="sino'+contLin+'" id="sino"style="display:none"><option value="1">Si </option><option value="2">No</option></select></td>'+
'<td> <select name="sexo'+contLin+'" id="sexo"  style="display:none"><option value="1">Masculino </option><option value="2">Femenino</option></select><td>'+
'<td><input type="button" value="+" class="clsAgregarFila"><input type="button" value="-" class="clsEliminarFila"></td>'+
'</tr>';

contLin++;

        var objTabla=$(this).parents().get(3);


        $(objTabla).find('tbody').append(strNueva_Fila);


        if(!$(objTabla).find('tbody').is(':visible')){

            $(objTabla).find('caption').click();
        }
    });


    $(document).on('click','.clsEliminarFila',function(){

        var objCuerpo=$(this).parents().get(2);
            if($(objCuerpo).find('tr').length==1){
                if(!confirm('Esta es el única fila de la lista ¿Desea eliminarla?')){
                    return;
                }
            }


        var objFila=$(this).parents().get(1);

            $(objFila).remove();
    });



});

Upvotes: 1

Views: 1882

Answers (1)

andyb
andyb

Reputation: 43823

The problem caused because $("#estado"+contLin).change(function () { is binding the function to the element #estado1 (since contLin=1 initially), but the JavaScript is executed when the document is ready and that element #estado1 does not exist.

One quick way to fix this is to move the change event function into $(document).on('click','.clsAgregarFila',function(){ body so that a new change function is bound to the new #estadoX when the table row is being appended. However this is very inefficient and I would advise using event delegation, which you are actually already using for the click handler functions on .clsAgregarFila and .clsEliminarFila.

Event delegation works by binding the handler function to a parent or ancestor DOM element which already exists. The event is then handled on that element and delegated down (by way of the CSS selector you specify) onto the target element.

For example $(document).on('click','.clsAgregarFila',function(){ means that the handler is not called when the event occurs directly on the bound element (document), but only for descendants (inner elements) that match the selector (all elements with class="clsAgregarFila") - see .on()

So you could just use the following, which uses the CSS attribute selector to match all <select> elements that start with id="estado". But there is a small problem - it will not work like this…

$(document).on('change', 'select[id^=estado]', function () {
    if ($("#estado"+contLin).val() == 2) {
        $("#sino"+contLin).show();
        $("#sexo"+contLin).hide();       
    }
    if ($("#estado"+contLin).val() == 3) {
        $("#sino"+contLin).hide();
        $("#sexo"+contLin).show();
    }
});

…since contLin == 2 as it is a global variable! What we really want is to find the <select>s on the current row. So the following amended function should work and even better can replace both of your functions, removing code duplication :-)

 $(document).on('change', 'select[id^=estado]', function () {
      var estadoValue = parseInt(this.value);
      var rowSelects = $(this).closest('tr').find('select').slice(1);

      $(rowSelects[0]).toggle(estadoValue === 2);
      $(rowSelects[1]).toggle(estadoValue === 3);
});

However, taking this approach further, your code could be rewritten like this demo. I have removed the HTML string and used .clone() to add a row, simplified removing a row, chained the event handling and removed the element counter - replacing with classes instead.

JavaScript

$(function(){
  var $tbody = $('tbody');
  var strNueva_Fila = $tbody.find('tr:first');

  $('tbody').on('change', 'select.estado', function() {
      var estadoValue = parseInt(this.value);
      var rowSelects = $(this).closest('tr').find('select').slice(1);

      $(rowSelects[0]).toggle(estadoValue === 2);
      $(rowSelects[1]).toggle(estadoValue === 3);
  }).on('click', 'input', function() {
      if (this.className === 'clsAgregarFila') {
        $tbody.append(strNueva_Fila.clone());
      } else if (this.className === 'clsEliminarFila') {
        $(this).closest('tr').remove();
      }

      buttonsToggle();
  });

  function buttonsToggle() {
    var $addButtons = $tbody.find('.clsAgregarFila');
    var $removeButtons = $tbody.find('.clsEliminarFila');

    // hide all
    $addButtons.hide();
    $removeButtons.hide();

    // show "-" button on all but first row
    $removeButtons.slice(0).show();

    // but hide "-" if there is only 1 row
    if ($removeButtons.length === 1) {
      $removeButtons.hide();
    }

    // show "+" button on last row only
    $addButtons.slice(-1).show();
  }
});

HTML (Note: I have added the "-" <input> and the <thead> and <tbody> elements).

<table>
  <thead></thead>
  <tbody>
      <tr>
      <td>
      <select id="estado" class="estado">
      <option value="1">Seleccione 1 opcion</option>
      <option value="2">Laboratorio</option>
      <option value="3">Datos Generales</option>
      </select>
      </td>
      <td>
      <!-- //laboratorio -->
      <select name="sino" class="sino" id="sino" style="display:none">
      <option value="1">Si </option>
      <option value="2">No</option>
      </select>
      </td>
      <td>
      <!-- //datos generales -->
      <select name="sexo" id="sexo" class="sexo" style="display:none">
      <option value="1">Masculino </option>
      <option value="2">Femenino</option>
      </select>
      </td>
      <td><input type="button" value="+" class="clsAgregarFila"/><input type="button" value="-" class="clsEliminarFila" style="display:none"/></td>
      </tr>
  </tbody>

Hope this helps :-)

Upvotes: 1

Related Questions