3

I think I might have done this... not in the best way. But it's working and the result is returned in my data object. Now I need to pass on some additional parameters. How can I call handleData() with additional parameters? I've tried this:

handleData({'likes' : true})

But that deletes the data object which is returned from the Ajax call.

Here is my code:

// My global Ajax function to 'set' data
$.fn.setData = function(url, params){
    return $.ajax({
        url: site_url + url,
        type: "POST",
        dataType: 'json',
        data: params
    });
}    

function registerLike() {
    var like    = $('.interaction .like')
    var status  = $(like).data('status');
    var count   = $(like).data('count');

    like.click(function(){
        if(!liked){
            // I need to pass adition parameters here
            like.setData('action/like', {'id' : id}).done(handleData());
        } else {
            // and here
            like.setData('action/unlike', {'id' : id}).done(handleData());
        }
    });

    function handleData(data){
        if(data.success) {

            if(data.likes){
                count = count+1;
                liked = 1;
            } else {
                if(count > 0) {
                    count = count-1;
                } else {
                    count = 0;
                }
                liked = 0;
            }

            $('.interaction .like .icon').toggleClass('el-icon-heart');
            $('.like-count').html(count);
        }
    }
}
Steven
  • 19,224
  • 47
  • 152
  • 257
  • Perhaps look into using the `success` handler of the `ajax` method, defining locally scoped variables each time and then calling `handleData` through that as opposed to using `done` – Rob Schmuecker Aug 05 '14 at 20:20
  • @RobSchmuecker No, not according to Alnitak "This decouples the callback handling from the AJAX handling, allows you to add multiple callbacks" http://stackoverflow.com/questions/14754619/jquery-ajax-success-callback-function-definition By returning the data, – Steven Aug 05 '14 at 20:30
  • Fair enough, has always done the trick for me though. – Rob Schmuecker Aug 05 '14 at 20:35
  • @RobSchmuecker While a valid workaround, it's still a workaround – Ruan Mendes Aug 05 '14 at 20:36
  • @JuanMendes I don't really understand? http://jsfiddle.net/robschmuecker/j5L49/ Here you can access the locally scoped variables in the `success` callback just fine? – Rob Schmuecker Aug 05 '14 at 20:58
  • @RobSchmuecker I may be wrong, but I think the point is that the success handler may need to be used somewhere else, so it can't be defined in the same closure – Ruan Mendes Aug 05 '14 at 20:59
  • @JuanMendes ah ok right, I see what you mean. – Rob Schmuecker Aug 05 '14 at 21:05

2 Answers2

4

You can always create a wrapper with an anonymous function:

like.setData('action/unlike', {'id' : id}).done(function(response){
    myCallback(response, extraData);
});
Amir Popovich
  • 29,350
  • 9
  • 53
  • 99
1

Amir's suggestion is a good one. However, it is generalized in Function.bind

like.setData('action/unlike', {'id' : id}).done( 
    myCallback.bind(this, extraData) 
);

Note that your function will be called like myCallback(extraData, response), not myCallback(response, extraData). If you really need extraData to be passed after the call time arguments, you can implement your own bind that appends the bound arguments instead of prepending them.

Ext-JS has a bind function that lets you choose where to insert the bound arguments.

/**
 * Create a new function from the provided `fn`, change `this` to the provided scope, optionally
 * overrides arguments for the call. (Defaults to the arguments passed by the caller)
 *
 * {@link Ext#bind Ext.bind} is alias for {@link Ext.Function#bind Ext.Function.bind}
 *
 * @param {Function} fn The function to delegate.
 * @param {Object} scope (optional) The scope (`this` reference) in which the function is executed.
 * **If omitted, defaults to the default global environment object (usually the browser window).**
 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
 * if a number the args are inserted at the specified position
 * @return {Function} The new function
 */
bind: function(fn, scope, args, appendArgs) {
    if (arguments.length === 2) {
        return function() {
            return fn.apply(scope, arguments);
        };
    }

    var method = fn,
        slice = Array.prototype.slice;

    return function() {
        var callArgs = args || arguments;

        if (appendArgs === true) {
            callArgs = slice.call(arguments, 0);
            callArgs = callArgs.concat(args);
        }
        else if (typeof appendArgs == 'number') {
            callArgs = slice.call(arguments, 0); // copy arguments first
            Ext.Array.insert(callArgs, appendArgs, args);
        }

        return method.apply(scope || Ext.global, callArgs);
    };
},

See http://docs-origin.sencha.com/extjs/4.2.2/#!/api/Ext.Function-method-bind

Community
  • 1
  • 1
Ruan Mendes
  • 90,375
  • 31
  • 153
  • 217