Clone a complete table without classes and validate both tables

1

I would like to leave you with the following concern, since I have been struggling for a long time with this and I have not been able to correct what happens.

I have this HTML:

<div class="clone-group" >
<table border="0" class="form-group cloneprop" >
    <tr >
        <td style="width: 70%;">
            NOMBRE O RAZ&Oacute;N SOCIAL
        </td>
        <td style="width: 18%;" align="center">
            RUT
        </td>
        <td style="width: 10%;" align="center">
            Agregar / Eliminar
        </td>
    </tr>
    <tr>
        <td>
            <input class="form-control required 3_nombre_prop _prop" readonly placeholder="Nombres" style="width: 38%; display: inline;" id="3_nombre_prop" value="" name="3_nombre_prop[]" type="text" />
            <input class="form-control required 3_apep_prop _prop" readonly placeholder="Apellido Paterno" style="width: 30%; display: inline;" id="3_apep_prop" value="" name="3_apep_prop[]" type="text" />
            <input class="form-control required 3_apem_prop _prop" readonly placeholder="Apellido Materno" style="width: 30%; display: inline;" id="3_apem_prop" value="" name="3_apem_prop[]" type="text" />
        </td>
        <td >
            <input class="form-control required 3_rut_prop" id="3_rut_prop" value="" name="3_rut_prop[]" type="text" />
            <input class="" type="hidden" id="3_rut_prop_x" name="3_rut_prop_x[]" value="" />
        </td>
        <td align="center" >
            <button type="button" class="btn btn-primary addButton" aria-label="Left Align" id="">
                <span class="glyphicon glyphicon-plus" aria-hidden="true"></span>Agregar
            </button>
        </td>
    </tr>
</table>
</div>
<input type="hidden" class="n_item_prop" name="n_item_prop" value="0">

Valid a rut in this table, without problems. But when I add a clone of this table with jQuery and try to validate that routine, the popover with the message always appears in the first table and not in the corresponding field, that is in the clone.

I have in the JS:

$(function(){
// PARA CLONAR
var i = parseInt($('.n_item_prop').val(), 10);
var bFlag1=i;
var cloneItem = $(".cloneprop:last");//class de la tabla
var cloneWrap   = $(".clone-group");//div
$(".addButton").on("click", function () {
    if(i < 4){
        bFlag1++;
        i = i + 1; 
        cloneItem.find('._prop').attr('readonly','readonly');
        var clon = cloneItem.clone(true).attr('id', 'pr_'+bFlag1).appendTo(cloneWrap);
        clon.find('[type=text]').val('');
        clon.find('[type=hidden]').val('');
        clon.find('[type=email]').val('');

        clon.find(".addButton")
    .replaceWith( '<button type="button" class="btn btn-primary remButton" aria-label="Left Align"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span>Eliminar</button>');

        $( ".n_item_prop" ).remove();
        str_id = '<input type="hidden" class="n_item_prop" name="n_item_prop" value="'+i+'">';
        $("#form_smpe").append(str_id);

    }
    if( $('#3_rut_prop').val()!="" ){
        var v1 = id_rut($('#3_rut_prop').val(), $("#3_nombre_prop"),$("#3_apep_prop"),$("#3_apem_prop"));

    }
});
$("body").on("click", ".remButton", function () {
    $(this).closest(".cloneprop").remove();
    i = i - 1;

    $( ".n_item_prop" ).remove();
    str_id = '<input type="hidden"  class="n_item_prop" name="n_item_prop" value="'+i+'">';
    $("#form_smpe").append(str_id);
});

// validate
$('#form').validate({
    ignore: '[readonly=readonly]',
    errorPlacement: function (error, element) {
        var lastError = $(element).data('lastError'), newError = $(error).text();
        $(element).data('lastError', newError);

        if (newError !== '' && newError !== lastError) {
            $(element).popover({
                trigger: "manual",
                placement: "auto top",
                content: newError,
                container: "body",
                template: "<div class=\"popover\" role=\"tooltip\"><div class=\"arrow\"></div><div class=\"popover-content\"><p></p></div></div>"
            });
            if (element.is(':hidden')) {
                    $(element).next('span').popover('show').addClass('has-error').removeClass('has-success');
                    console.log('hidden element');
            }else {
                $(element).popover("show").parents(".form-group").addClass('has-error').removeClass('has-success');
                console.log('normal element');
            }
        }
    },  
    success: function (label, element) {
        $(element).popover("hide").parents(".form-group").removeClass('has-error').addClass('has-success');
    },

    rules: {
        "3_rut_prop[]": {
            required: true
        }
    },
    messages: {
        "3_rut_prop[]": {
            required: "Debe ingresar un dato válido"
        }
    }
});

// VALIDA RUT
$.validator.addMethod("3_rut_prop", function(value, element){
    return this.optional(element) || $.Rut.validar(value);
}, "Este campo debe ser un rut valido.");
$('#3_rut_prop').Rut({
    validation: false
});

});

For jQuery validations, I have the following calls;

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script type="text/javascript" src="js/bootstrap.min.js"></script>
<script type="text/javascript" src="js/jquery-ui.js"></script>
<script type="text/javascript" src="js/jquery.Rut.js"></script> 
<script type="text/javascript" src="js/jquery.validate.js"></script>
<script type="text/javascript" src="js/additional-methods.js"></script>
<script src="js/ie10-viewport-bug-workaround.js"></script>
<script type="text/javascript" src="js/validate_v.js"></script>

As I mentioned, with this I validate the table rout. But when trying to validate the rout of the cloned table, the popover with the message always appears in the first table.

    
asked by x_Mario 21.03.2016 в 19:58
source

1 answer

0

There are several things that can create problems:

  • jQuery Validate uses the name attribute to identify the different rules and messages to display and therefore does not work very well with input s that have the same attribute name (eg : in dynamic forms in which the user can add fields with the same name).
  • Apart from that, the code presents repeated IDs (within the elements of the tables), which also seems to cause problems with the jQuery Validator plugin when displaying error messages .
  • In addition, validation rules apply to existing fields when you call validate() . That is, the fields that are added after dynamically do not have the associated validation.

But that does not mean that it can not be done ... only that a few changes will have to be made to make it work. At least:

  • Delete duplicate IDs
  • Remove duplicate names
  • Add validation to dynamic fields.
  • Let's start with parts. But keep in mind that I have not been able to test all the following code because some of the functions are missing from the code above and I had to invent them to do tests. The idea is to give you a base so you can continue and complete it yourself.

    Step 1: Remove the IDs from the fields to be cloned

    Delete all ID's in the fields within the table. In this way when the tables are cloned, there will be no duplication of ID's and you will save yourself problems (not only with jQuery Validate, but also other possible problems when selecting elements).

    Since you have the same value as the ID also as a class name, that will make it easier to adapt if you have styles associated with the ID. Also, being easy to identify by the class name is going to be good later.

    For example, this would change some of the lines of code you have:

    <td>
      <input class="form-control required 3_nombre_prop _prop" readonly placeholder="Nombres" style="width: 38%; display: inline;" value="" name="3_nombre_prop[]" type="text" />
      <input class="form-control required 3_apep_prop _prop" readonly placeholder="Apellido Paterno" style="width: 30%; display: inline;" value="" name="3_apep_prop[]" type="text" />
      <input class="form-control required 3_apem_prop _prop" readonly placeholder="Apellido Materno" style="width: 30%; display: inline;" value="" name="3_apem_prop[]" type="text" />
    </td>
    <td >
      <input class="form-control required 3_rut_prop" value="" name="3_rut_prop[]" type="text" />
      <input class="3_rut_prop_x" type="hidden" name="3_rut_prop_x[]" value="" />
    </td>
    

    Step 2: Make the names of the fields unique

    jQuery Validate has problems when two fields have the same attribute name (or the same attribute id , but that we have already solved) and shows the error messages only in the first one that you find (this is a part of the problem you have with the validation). But you want them to have the same name with brackets (I suppose to make it easier to process in PHP, which will read all values as an array).

    There is an alternative, although not entirely clean, so that all fields have a different name attribute and PHP will continue to process them as an array when they receive the form data: use indexes in the brackets.

    The idea is simple: in the same way that you add a unique id to the row when it is created (using bFlag1 ), you can add a name unique to each field within of event click of addButton :

    clon.find('[name]').each(function() {
        $(this).attr("name", $(this).attr("name").replace("[]", "[" + bFlag1 + "]") );
    });
    

    In this way, all the fields will have unique IDs, but PHP will continue reading them as an array when the form is sent (even if the indexes are not consecutive after deleting some table).

    Step 3: Add validation to dynamic fields

    When fields are generated dynamically we no longer have repeated IDs and all fields have a unique name ... now we only need to add the validation rules to these fields. And for that we're going to use the rules() method.

    With rules() you can read, add or remove validation rules to a given element; and specifically we want the add part, whose format is as follows:

    $(elemento).rules('add', { 
        ...reglas de validación...
    })
    

    In your case, this would be after the clone was added to the DOM in the event click of addButton . You would have to search the different fields to be validated (they have a characteristic class) and add the validation rules using rules .

    It seems that only the 3_rut_prop field is valid, so it should not be very different from this:

    clon.find(".3_rut_prop").each(function() {
        $(this).rules('add', {
            required: true,
            messages: {
                required: "Debe ingresar un dato válido"
            }
        });
    });
    

    I know it's a long answer. Try to follow the steps and comment / ask if you have a problem.

        
    answered by 22.03.2016 / 04:49
    source