0

I have this code http://jsfiddle.net/meridius/ysDGm/ where the problem is with out.id variable in append part. For reasons I can't explain, that variable is empty in that part.

I think the problem is with that variable's scope and I tried everything but with no luck. Please note, the problem is NOT with AJAX, that works fine!

Here is shortened version of that Fiddle:

<tr>
    <td>one</td>
    <td>
        <select name="zadavatel">
            <option value="0">-- vyberte --</option>
            <option value="new">-- nový zadavatel --</option>
        </select>
    </td>
</tr>
var out = {};
$('select').bind("change", function() {
  if ($(this).val() == "new") {
    var nazev = prompt('Question', 
                $(this).parent().siblings(':first-child').text());
    if (nazev == null) {
      $(this).val($.data(this, 'current'));
      return false;
    } else {
      var pole2 = {};
      pole2["nazev"] = nazev;
      $.ajax({
        type    : "POST",
        cache    : false,
        url      : "./pokus_zad.php",
        data    : JSON.stringify(pole2),
        success  : function(data) {
          out = JSON.parse(data);  //data.id
        }
      });
      out.id = 15;  // this work, but it SHOULD work without it (with AJAX)
      $(this).closest('table').find('select').each(
        function() {
          $(this).append($('<option>', { "value" : out.id }).text(nazev));
        });
      $(this).closest('select').val(out.id).attr('selected', 'selected');
    }
  }
  $.data(this, 'current', $(this).val());
});
Mike Mackintosh
  • 13,917
  • 6
  • 60
  • 87
meridius
  • 1,495
  • 1
  • 18
  • 26
  • 2
    Search for "return jquery ajax value". You will find enough duplicates. The cause is very simple: *the value of the [global] variable has not been set at the point it is used*. Thats all. –  Jul 16 '12 at 18:35
  • http://stackoverflow.com/questions/560307/how-do-i-edit-a-global-variable-in-a-jquery-each-function?rq=1 , http://stackoverflow.com/questions/6917796/extjs-return-ajax-return-value , http://stackoverflow.com/questions/8532082/return-value-of-post-call , http://stackoverflow.com/questions/31129/how-can-i-return-a-variable-from-a-getjson-function?rq=1 , http://stackoverflow.com/questions/1632039/return-value-from-ajax-call , http://stackoverflow.com/questions/1181665/is-there-a-way-to-return-a-value-xml-in-my-case-from-a-jquery-ajax-call?rq=1 –  Jul 16 '12 at 18:38
  • 1
    AJAX is asynchronous, so code flow continues while the ajax call is being performed. You are trying to use your `out` variable before it gets set. Try moving the code after your ajax call into the success callback – MrOBrian Jul 16 '12 at 18:41
  • The rest of your code executes while the ajax call is doing its thing. Put your in the success function or setup a callback, or eve better a deferred. – Jack Jul 16 '12 at 18:42

3 Answers3

0

AJAX is asynchronous, and therefore the setting of the out variable from within it will happen after the rest of the function.

      $.ajax({
        type    : "POST",
        cache    : false,
        url      : "./pokus_zad.php",
        data    : JSON.stringify(pole2),
        success  : function(data) {
          out = JSON.parse(data);  //data.id
          $(this).closest('table').find('select').each(
            function() {
              $(this).append($('<option>', { "value" : out.id }).text(nazev));
            });
          $(this).closest('select').val(out.id).attr('selected', 'selected');
        }
      });
Inkbug
  • 1,682
  • 1
  • 10
  • 26
0

You should put the append code inside the success block. Because the ajax call is asynchronous the append statement runs before the 'out' variable is set by the ajax callback.

var out = {};
$('select').bind("change", function() {
  if ($(this).val() == "new") {
    var nazev = prompt('Question', 
                $(this).parent().siblings(':first-child').text());
    if (nazev == null) {
      $(this).val($.data(this, 'current'));
      return false;
    } else {
      var pole2 = {};
      pole2["nazev"] = nazev;
      $.ajax({
        type    : "POST",
        cache    : false,
        url      : "./pokus_zad.php",
        data    : JSON.stringify(pole2),
        success  : function(data) {
          out = JSON.parse(data);  //data.id
          $(this).closest('table').find('select').each(
            function() {
              $(this).append($('<option>', { "value" : out.id }).text(nazev));
            });
          $(this).closest('select').val(out.id).attr('selected', 'selected');
        }
      });
    }
  }
  $.data(this, 'current', $(this).val());
});
Yoni Baciu
  • 2,667
  • 1
  • 22
  • 28
0

Great, thanks guys!

Based on your suggestions I moved my append code to success callback of AJAX function AND I also had to create variable for $(this) since it is different $(this) inside AJAX than it is outside. ;)

The working JQuery part now looks like this:

var out = {};
$('select').bind("change", function() {
    if ($(this).val() == "new") {
        var nazev = prompt('Zadejte název zadavatele', $(this).parent().siblings(':first-child').text());
        if (nazev == null) {
            $(this).val($.data(this, 'current'));
            return false;
        } else {
            var select = $(this);
            var pole2 = {};
            pole2["nazev"] = nazev;
            $.ajax({
                type        : "POST",
                cache       : false,
                url         : "./pokus_zad.php",
                data        : JSON.stringify(pole2),
                success : function(data) {
                    out = JSON.parse(data); //data.id
                    select.closest('table').find('select').each(
                        function() {
                            $(this).append($('<option>', { "value" : out.id }).text(nazev));
                        });
                    select.val(out.id).attr('selected', 'selected');
                }
            });
        }
    }
    $.data(this, 'current', $(this).val());
});
meridius
  • 1,495
  • 1
  • 18
  • 26