0

I am having difficulty traversing with jQuery. I have a form with a dynamic set of dropdown boxes, and am trying to call particular actions based on element class instead of id, as this form can be cloned in my application.

Any ideas why my traversing isn't working? Is my $(this) call becoming voided somehow?

HTML:

<div>
    <label>Item:</label>
    <select class="item" name="item" id="item"> 
        <option value="">Select</option>
        ...
    </select>
</div>          
<div>
    <label class="label>Options:</label>
    <select class="options" name="options" id="options">

        ...
    /select>
</div>          

Javascript:

$(".item").change(function () { 

  var group_id = $(this).val();

   $.ajax({
        type: "POST", 
        url: "../../db/items.php?id=" + group_id, 
        dataType: "json",
        success: function(data){
            $(this).parent().next().children('select.options').empty(); 
            $(this).parent().next().children('select.options').append('<option value="">Select</option>');
            $.each(data, function(i, val){    
               $(this).parent().next().children('select.options').append('<option value="' + val.group_id + '">' + val.name + '</option>');
            });
            $(this).parent().next().children('select.options').focus();
        },
        beforeSend: function(){
            $(this).parent().next().children('select.options').empty();
            $(this).parent().next().children('select.options').append('<option value="">Loading...</option>');
        },
        error: function(){
            $(this).parent().next().children('select.options').attr('disabled', true);
            $(this).parent().next().children('select.options').empty();
            $(this).parent().next().children('select.options').append('<option value="">No Options</option>');
        }
    })  

});
Michael
  • 2,276
  • 15
  • 49
  • 80

3 Answers3

1

this is no longer the DOM element that the event was triggered on. You can set the value of this by using the context option of $.ajax:

$(".item").change(function () {
    $.ajax({
        /* options */
        context: this,
        success: function () {
            // this is now the element that was changed
        }
    });
});

You could also store the value of this in a variable and use it in your callback:

$(".item").change(function () { 

  var group_id = $(this).val();
  var self = this;

   $.ajax({
        type: "POST", 
        url: "../../db/items.php?id=" + group_id, 
        dataType: "json",
        success: function(data){
            // use "self" instead of "this"
        }
    })  

});

Another note: You should consider caching your selectors for greater performance (and readability). Also, you can chain together jQuery function calls:

var $children = $(this).parent().next().children('select.options')
    .empty()
    .append('<option value="">Select</option>');

$.each(data, function(i, val){    
   $children.append('<option value="' + val.group_id + '">' + val.name + '</option>');
});
$children.focus();
Andrew Whitaker
  • 124,656
  • 32
  • 289
  • 307
  • I didn't now that about the context attribute in the ajax call. That seems cleaner that defining another variable as I suggested as well. – Matt Moore Jan 06 '12 at 22:44
1
 var group_id = $(this).val();
 var myThis = $(this);

   $.ajax({
        type: "POST", 
        url: "../../db/items.php?id=" + group_id, 
        dataType: "json",
        success: function(data){
            myThis.parent().next().children('select.options').empty(); 
        ...
John Fable
  • 1,081
  • 7
  • 11
0

Yup, $this now refers to the success function in your ajax call. Add this line.

$(".item").change(function () {  

  var group_id = $(this).val(); 
  var item = $(this); // Added line

Now in your ajax function use item where you use $this.

Matt Moore
  • 581
  • 2
  • 6