Roger
Roger

Reputation: 8576

JQuery: what's the simplest way to inject html via ajax into the DOM?

I am building a interactive form and injecting new questions via ajax according to the answers users give.

My problem is that it looks like the injected html is invisible to JQuery.

As you can see http://atpc.info/f/pesquisa1.htm the click function doesn't work in the injected HTML.

//pesquisa1.js
$('a.continuar_r').live('click',function(event) {
    var id_p=$('input:radio:first').attr('name');
    var v_r=$('input:radio:checked').val();
    alert(v_r);
    if (!v_r) $('#update_p').hide().text('Ops! Selecione uma opção').fadeIn('slow');
    else {
        $('#update_p').hide();
        var fieldset=$(this).closest('fieldset');
        fieldset.hide();
        fieldset.nextAll('fieldset:first').fadeIn('slow');

        $.post(
            'pesquisa1.php',
            { id_p:id_p, v_r:v_r },
            function(data){
                //alert('Retorno:\n' + data);
                $('#status_p').hide();
                $('form').append($(data).hide().fadeIn('slow'));
                $('label').css('display','block');
            }
        );
    }

});

By the way, "id_p" it's the id of the question and "v_r" it's the value of the answer (the chosen option or the written answer).

Now the HTML:

//pesquisa1.htm
<form id="form_p" action="">

    <input type="hidden" id="origem_p" value="">
    <input type="hidden" id="proposito_p" value="">

    <fieldset class="p_satisfeito">
        <legend>Você está satisfeito com os seus resultados atuais?</legend>
        <label for="for_s"><input type="radio" id="for_s" name="p_satisfeito" value="s">Sim</label>
        <label for="for_n"><input type="radio" id="for_n" name="p_satisfeito" value="n">Não</label>
        <a class="continuar_r">Continuar &rarr;</a>
    </fieldset>

    <small id="update_p"></small> <span id="status_p"></span>

</form>

I am presenting here a very simplified version of the PHP code, which is a interactive form.

//pesquisa1.php
<?
echo<<<FORM
<label for="for_y1"><input type="radio" id="for_y1" name="p_satisfeito1" value="ohy">Oh, Yes!</label>
<label for="for_n1"><input type="radio" id="for_n1" name="p_satisfeito1" value="ohn">Oh, No!</label>
<a class="continue_r">Continue &rarr;</a>
FORM;
?>

It looks like I can't use the javascript that is already loaded to interact with the new html that has just been loaded...

EDIT:

If I insert some javascript in my php, the magic comes back but I still can't access the variables declared in the first page load.

//form.php//
<?
echo<<<FORM
<label for="for_y1"><input type="radio" id="for_y1" name="p_satisfeito1" value="ohy">Oh, Yes!</label>
<label for="for_n1"><input type="radio" id="for_n1" name="p_satisfeito1" value="ohn">Oh, No!</label>
<a class="continue_r">Continue &rarr;</a>
<script>
    $('a.continue_r').click(function(event) {
        alert('Hi!');
        var id_p=$('input:radio:first').attr("name")
        alert('id_p');
    });
</script>
FORM;
?>

Thank you!

Upvotes: 0

Views: 1185

Answers (3)

Naveed
Naveed

Reputation: 11167

Try jQuery live method!

//form.js//

$(document).ready(function() {
  $('a.continue_r').live("click",function(event) {
    var id_p=$('input:radio:first').attr("name")
    var v_r=$('input:radio:checked').val();
    $.post(
        'form.php',
        { id_p:id_p, v_r:v_r },
        function(data) {
            alert('Return:\n' + data);
            $('#stage').html(data).fadeIn('slow');
            $('#stage').css('display','block');
            $('label').css('display','block');
        }
    );
  });
});

Hopefully it will work.

Upvotes: 1

ghbarratt
ghbarratt

Reputation: 11711

I believe this is an issue of replacement and scope. You are replacing the html of #stage with what is sent back, then you are trying to get id_p through the DOM but you had just replaced that content. Also, I am guessing you originally intended to use id_p and v_r since they are declared but never used. Because those vars are declared within the function for post they will not be available later when you need them. You will need to declare them in a higher scope.

Lastly I noticed that in form.php, you are attempting to get the name of an element, but you are setting the element in the same file.. Do you really need the name?

One more thing. My guess is that you are trying to collect the responses to a series of questions, which load individually through ajax, right? ... If you have more than 2 questions, then consider putting the response in an array.

Try this:

new html:

<script type="text/JavaScript"> 

  var responses = [];

  $(document).ready
  (
    function()
    {
      loadPergunta();
      $("a.continuar").click
      (
        function()
        {
          var response  = $("#pergunta input:checked").val();
          if(typeof(response)=="undefined") response = $("#pergunta input").val();
          alert(response);
          responses[responses.length] = response;
          loadPergunta(responses.length+1);
        }
      );
    }
  );

  function loadPergunta(id)
  {
    if(typeof(id)=="undefined") id = 1;
    $('#stage').fadeOut('slow');
    $.post(
      'pergunta.php',
      {id: ""+id},
      function(data) {
        if(data.toLowerCase().indexOf('input')==-1)
        {
          $("a.continuar").fadeOut("slow");
        }
        $('#pergunta').html(data).fadeIn('slow');
      }
    );
  }

</script>


<div id="box">
  <fieldset id="pergunta"></fieldset>
  <a class="continuar">Continuar &rarr;</a>
</div>

and pergunta.php:

<?php

  $p_id = (int)($_POST['id']);

  $perguntas = array
  (
    1 => array
    (
      'type' => 's_ou_n',
      'text' => 'Você está satisfeito com os seus resultados atuais?'
    ),
    array 
    (
      'type' => 's_ou_n',
      'text' => 'Você recommendará nossos servicos aos seus amigos?' 
    ),
    array
    (
      'type' => 'text',
      'text' => 'Algo mais que quer compartilhar?'
    )
  );

  $content = '';

  if($p_id<=count($perguntas)) 
  {
    if($perguntas[$p_id]['type']=='s_ou_n')
    {
      $content = '<div class="pergunta-text">'.$perguntas[$p_id]['text']."</div>\n";
      $content .=
      '
      <input type="radio" id="p_'.$p_id.'_s" name="p_'.$p_id.'" value="s"><label for="p_'.$p_id.'_s">Sim</label>
      <input type="radio" id="p_'.$p_id.'_n" name="p_'.$p_id.'" value="n"><label for="p_'.$p_id.'_n">Nao</label>
      ';
    }
    else
    {
      $content =
      '
        <label for="p_'.$p_id.'" class="pergunta-text">'.$perguntas[$p_id]['text'].'</label> <input type="'.$perguntas[$p_id]['type'].'" id="p_'.$p_id.'" name="p_'.$p_id.'" ></input>
      ';
    }
  }
  else $content = 'Obrigado pela participação!';

  echo $content;
?>

Upvotes: 1

F&#233;lix Saparelli
F&#233;lix Saparelli

Reputation: 8719

You aren't injecting the data returned from your POST request anywhere, so nobody knows about it. You could do it like that:

$.post('form.php', {params...}, function(html) {
  $('body').append(html);
  // Now it's in the DOM, you can access it.
}, "text");

Upvotes: 1

Related Questions