Load content dynamically with AJAX

Asked

Viewed 2,385 times

6

I have the following HTML code:

  <label id="meuTemplate" for="criaAssoc" class="instAssoc" style="display:none">

  <strong>ID:</strong>
    <input name="idInstrucao" type="text">
  <strong>Ordem:</strong>
    <input type="text">

  <span>
    <strong class="instTxt">Instrução:</strong>
    <textarea disabled="disabled"></textarea>
  </span>

  <img src="images/1.png" title="Remover instrução" class="botaoExcluir" >

</label>

Which has the following result as in the print below: inserir a descrição da imagem aqui

Through this JS code (below) using jQuery by clicking the button more I can clone the label passed in the HTML above.

//Script para adicionar labels
var ids = 1;

$(".btnNewInst").click(function(){
    var novoId = "lb_" + (ids++);

    var clone = $("#meuTemplate").clone();
    clone.prop("id", novoId); // É necessário mudar o id depois que se clona
    $(".instAssoc:last").after("<br>", clone);
    clone.show();

    clone.find(".botaoExcluir").click(function() {
        clone
            .prev().remove().end() // Remove também o <br>
            .remove();
    });

});

//Disparando evento click para criar a primeira label
$(".btnNewInst").click(); 

The result of cloning is this: inserir a descrição da imagem aqui

However I use a JS code using Ajax to read information from my database. But, I can’t do this label by label, I can only succeed on the first label. The next ones that are cloned Ajax cannot run. And it even manages if the label has already been cloned before the event that triggers Ajax is triggered, but it only runs on the first label. The information that was to come out in the second does not come out, only clones the information of the first label. Follows a print of the situation described. inserir a descrição da imagem aqui

Below is the script that is AJAX:

//Ajax para recuperar o texto da instrução passando o ID
$("input[name='idInstrucao']").focusout(function(){

    $.ajax({
        url: 'ajax/instrucaoAjax.php',
        type: 'POST',
        data: 'idInstrucao='+$(this).val(),
        beforeSend: '',
        error: function(leitura){
            $("textarea").val(leitura);
        },
        success: function(leitura){      

            if(leitura == 1){
                $("textarea").val("Esta pergunta não existe!");    
            }else{
                $("textarea").val(leitura);
            }
        }
    });

});

Any suggestions for this BUG?

Updating:
I made the changes as suggested. But the problem persists. Now it no longer replicates the result of the first label in the second. However, it doesn’t work on cloned labels. Look how my script looks after the changes:

//Script para adicionar labels
var ids = 1;

$(".btnNewInst").click(function(){
    var novoId = "lb_" + (ids++);

    var clone = $("#meuTemplate").clone();
    clone.prop("id", novoId); // É necessário mudar o id depois que se clona
    $(".instAssoc:last").after("<br>", clone);
    clone.show();

    $(document).on('click', '.botaoExcluir', function() {
        $(this).closest('label')
            .prev().remove().end() 
            .remove();
    });

});

//Disparando evento click para criar a primeira label
$(".btnNewInst").click(); 

//Ajax para recuperar o texto da instrução passando o ID

$("input[name='idInstrucao']").focusout(function(){

    var valor = this.value;

    var self = this;

    var textArea= $(self).closest('label').find('textarea');

    $.ajax({
        url: 'ajax/instrucaoAjax.php',
        type: 'POST',
        data: 'idInstrucao='+valor,
        beforeSend: '',
        error: function(leitura){
            alert(leitura);
        },
        success: function(leitura){      

            if(leitura == 1){
                textArea.val("Esta pergunta não existe!");    
            }else{
                textArea.val(leitura);
            }
        }
    });

});

1 answer

4


I think your problem is the "Scope"/scope of the this within the $.ajax that is in the wrong context, pointing to the ajax function and not to the element that triggered the event.

Try it like this:

$("input[name='idInstrucao']").focusout(function(){
    var valor = this.value; // ou var self = this;
    $.ajax({
        url: 'ajax/instrucaoAjax.php',
        type: 'POST',
        data: 'idInstrucao='+valor , // no caso de usar self, use 'idInstrucao='self.value

In addition, in case you want to refer to textarea correct could do so for example:

        // antes de entrar na função ajax
        var self = this;
        var textArea= $(self).closest('label').find('textarea');

        // dentro da função sucesso do ajax:
        if(leitura == 1){
            textArea.val("Esta pergunta não existe!");    
        }else{
            textArea.val(leitura);
        }

By the way, another problem, or possible optimization, is this part of your code:

clone.find(".botaoExcluir").click(function() {
    clone
        .prev().remove().end() // Remove também o <br>
        .remove();
});

It seems to me better to do as below and remove it from the function that generates a new clone:

$(document).on('click', '.botaoExcluir', function() {
    $(this).closest('label')
        .prev().remove().end() 
        .remove();
});

EDIT:

Two suggestions after your corrected code:

the method .clone() accepts parameters, the first is a boolean to be able to clone the events. This was missing my answer, because without it the new input never fires the focusout. So use: var clone = $("#meuTemplate").clone(true);

the second is repeated, take this code down out of the click function, otherwise it will add multiple events. And it doesn’t take more than once, since you’re deputy:

$(document).on('click', '.botaoExcluir', function() {
    $(this).closest('label')
        .prev().remove().end() 
        .remove();
});

Complete code here

  • 1

    Yeah! Spun... perfectly! Vlw @Sergio

Browser other questions tagged

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