0

I am quite newbie in OOP. I have lots of ajax calls and i want to combine them as an object.

Here is my function;

var Ajax_call = function(target) {
    this.target = target;
    this.data = function(){
        return $("#"+this.target+"").parent("form").serialize();
    };
    this.start = function(){
        status(true);
        var data = this.data();
        $.ajax({
            type : "post",
            url : $("#"+this.target+"").attr('action'),
            data : data + '&ajax=' + 1,
            dataType : "json",
            timeout : 3000,
            success : 
                function(serv){
                    if(serv.error){
                        this.denied();  ///// TypeError: undefined is not a function 
                        }
                    if(serv.done){
                        //this.succeed();
                        }
                    },
            error :
                function(x,t,m){
                    //this.failed();
                }
        });
    };

};

I want to define denied() method here;

$('body').on('click','#register_submit',function(event){
    event.preventDefault();
    Ajax_call.denied = function() {
        console.log (serv.error);
    };
    var register = new Ajax_call((this.id));
    register.start();
});

Thanks!


HERE IS THE SOLUTION;

I defined duplicated variable this to _this. So when js overload on it i can use _this instead of this. There is no need for prototype.

Declaration;

var Ajax_call = function(target) {
    this.target = target;
    this.data = function(){
        return $("#"+this.target+"").parent("form").serialize();
    };
    this.denied;
    this.start = function(){
        var _this = this; /// Js overload on this.
}

Ajax part;

    $.ajax({
        type : "post",
        url : $("#"+this.target+"").attr('action'),
        data : data + '&ajax=' + 1,
        dataType : "json",
        timeout : 3000,
        success : 
            function(serv){
                if(serv.error){
                    _this.denied(serv);  ///// Fixed
                    }
                if(serv.done){
                    //_this.succeed();
                    }
                },
        error :
            function(x,t,m){
                //_this.failed();
            }
    });

Usage;

$('body').on('click','#register_submit',function(event){
    event.preventDefault();
    var register = new Ajax_call((this.id));
    register.denied = function(serv) {
        console.log (serv.error);
    };
    register.start();
});
  • Doesn't make sense to set the prototype method on every click. If multiple calls happen at the same time (multiple instances) the second one will overwrite the first denied method. Maybe the following answer helps: http://stackoverflow.com/questions/16063394/prototypical-inheritance-writing-up/16063711#16063711 – HMR Jun 11 '14 at 01:11
  • uhmm. i wont use this object in one page multiple times. can't it be a basic solution to set clicked button's attr disabled? or you think i must use constructor? great article by the way.. i am trying to get it thank you. – Levent Çorapsız Jun 11 '14 at 02:58
  • If you don't need multiple instances then why a constructor function to create only one instance? You could declare register as an object literal: `var register = {prop1:22,prop2:function(){}}` You'll only ever have one register object and can manipulate that. I have to say that with Ajax it's better to create multiple instances as you may make multiple ajax calls at the same time. Manipulate instance specific members when needed and define shared members that won't change per instance on the prototype. – HMR Jun 11 '14 at 06:41
  • yes there might be multiple ajax call at the same time in the future. so updated the solution. if i create another object like `var lost-password = new Ajax_call();` i think there will be no problem. they will all have unique `denied` property. am i right? or any changes needed? – Levent Çorapsız Jun 11 '14 at 07:44
  • Correct, you can place the start function on Ajax_call.prototype. – HMR Jun 11 '14 at 08:01
  • You're welcome, hope it works out. Takes a bit of time to wrap your head around it but will give you great benefit once you do. – HMR Jun 11 '14 at 08:22

2 Answers2

0

it's the scope issue for this as this has special meaning (i.e., pointing to the object the callback is called from) in callback function. Save this in a local variable and use it later. See the example below.

this.start = function(){
        var self = this;
        status(true);
        var data = this.data();
        $.ajax({
            type : "post",
            url : $("#"+this.target+"").attr('action'),
            data : data + '&ajax=' + 1,
            dataType : "json",
            timeout : 3000,
            success : 
                function(serv){
                    if(serv.error){
                        // this is replaces with self variable
                        self.denied();  ///// TypeError: undefined is not a function 
                        }
                    if(serv.done){
                        //this.succeed();
                        }
                    },
            error :
                function(x,t,m){
                    //this.failed();
                }
        });
    };
Kamrul
  • 7,175
  • 3
  • 31
  • 31
0

The this in this.denied(); refers to that success function, not Ajax_call. So setting the denied method later is working but its not getting seen properly because of how JS overloads this.

What you probably want is to bind this to that success function using something like underscore.js's bind().

Which would then look something like:

// ...
success: _.bind(function(serv){
    if(serv.error){
        this.denied();
    }
    if(serv.done){
        //this.succeed();
    }
}, this),
// ...
Darrell Brogdon
  • 6,843
  • 9
  • 47
  • 62
  • **its not getting seen properly because of how JS overloads this.** That's the answer i was looking for. Thank you so much i can fix it without underscore.js – Levent Çorapsız Jun 10 '14 at 23:38