开发者

Using Ajax callback variable values in JQuery dynamic click handlers

I'm doing a simple ajax query which retrieves a variable-length list of values as JSON data. I'm trying to make a list based on this data which has click-functions based on the values I got from the JSON query. I can make this work just fine by writing the onClick-methods into the HTML like this:

function loadFooList() {
    var list_area = $("#sidebar");
    list_area.html("<ul>")
    $.ajax({
    type: 'GET',
        url:'/data/foo/list',
    dataType: 'json',
    success: function (json) {
        $.each(json, function(i, item) {
        var link_id = "choosesfoo" + item.id;
        list_area.html(list_area.html()
                   + "<li> <a href='#' onClick='alert(\"" + 
                   link_id + "\");'>" + 
                   item.name + "</a></li>");
        });
        list_area.html(list_area.html() + "</ul>");
    }
    });
}

I don't like writing the onClick-function into the HTML and I also want to learn how to create this same functionality via JQuery click-function.

So the problem is obviously variable-scoping. My naive attempt here obviously won't work because the variables are no longer there when the click happens:

function loadFooList2() {
    var list_area = $("#sidebar");
    var link_ids = Array();
    list_area.html("<ul>")
    $.ajax({
    type: 'GET',
        url:'/data/foo/list',
    dataType: 'json',
    success: function (json) {
        $.each(json, function(i, item) {
        var link_id = "choosefoo" + item.id;
        list_area.html(list_area.html()
                   + "<li> <a href='#' id='" + link_id  + "'>"+item.name+"</a></li>");
        link_ids.push(link_id);
        });
        list_area.html(list_area.html() + "</ul>");
        for (link_index=0; link_index<link_ids.length; link_index++) {
        $("#" + link_ids[link_index]).click(function() {
            alert(link_ids[i]); 
        });
        }
    }
    });
}

Obviously I'd like to do something else than just alert the value, but the alert-call is there as long as I can get that working and move forward.

I understand that I'll have to make some kind of handler-function to which I pass a state-variable. This works for a single value (I can store the whole link_ids array just fine, but then I don't know which of them is the right value for this link), but how would I do this for arbitrary-length lists?

Here is an example from JQuery docs which I'm trying to copy:

 // get some data
 var foobar = ...;

 // specify handler, i开发者_如何学运维t needs data as a paramter
 function handler(data) {
   //...
 }

 // add click handler and pass foobar!
 $('a').click(function(){
   handler(foobar);
 });

 // if you need the context of the original handler, use apply:
 $('a').click(function(){
   handler.apply(this, [foobar]);
 });

And I quess the last example here, "if you need the context of the original handler..." would probably be what I want but I don't know exactly how to get there. I tried to store the current link_id value into this, use it from this in the applied function (using apply()) but I didn't succeed. The necessary values were still undefined according to FireFox. I'm using JQuery 1.3.2.

So what's the right solution for this relatively basic problem?


Use append instead of html():

function loadFooList() {
    var ul = $('<ul>');
    $.ajax({
        type: 'GET',
        url:'/data/foo/list',
        dataType: 'json',
        success: function (json) {
            $.each(json, function(i, item) {
                var link_id = "choosesfoo" + item.id;
                var a = $('<a>').attr('href','#').bind('click', function(e) {
                    alert(link_id,item_name);
                    e.preventDefault();
                });
                $('<li>').append(a).appendTo(ul);
            });
            ul.appendTo('#sidebar');  // this is where the DOM injection happens
        }
    });
}


So the problem appears to be getting the link id associated with the link so that your click handler has access to it. Note that if it's alphanumeric it will qualify for the id attribute and you can extract it from there. If it is purely numeric, it will be an illegal id attribute. In that case, you can either use an attribute, like rel, or the jQuery.data() method to store the link id with the link. You can also simplify by using append. I'll show both examples.

var link = $("<li><a href='#' id='" + link_id + "'>" + item.name + "</a></li>";
link.click( function() {
         alert( $(this).attr('id') );
     });
list_area.append(link);

or (if numeric)

var link = $("<li><a href='#'>" + item.name + "</a></li>";
link.data('identifier', link_id )
    .click( function() {
         alert( $(this).data('identifier') );
     });
list_area.append(link);


Try this:

function loadFooList() {
    var list_area = $("#sidebar");
    $.ajax({
        type: 'GET',
        url:'/data/foo/list',
        dataType: 'json',
        success: function (json) {
            var out = '<ul>';
            $.each(json, function(i, item) {
                var link_id = "choosefoo" + item.id;
                out +="<li><a href='#' id='" + link_id  + "'>"+item.name+"</a></li>";
            });
            out +="</ul>"
            var $out = $(out);
            $out.find('a').click(function(){
                var link_id = this.id;
                var item_name = $(this).text();
                alert(link_id);
                alert(link_name);
            })
            list_area.html($out);
        }
    });
}

Using multiple appends causing the browser to redraw multiple times in a row. You only want to modify the dom once.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜