Matthieu Kaiser Matthieu Kaiser - 3 months ago 11
Ajax Question

Post a javascript object with prototype

Requirements:


  • I would create an javascript object with methods and properties.

  • I would post this object.



My code:

var SessionManager = (function (my) {
function addUrl(urlHistory) {
if (!urlHistory) throw new TypeError('"urlHistory" is null or not defined');
if (!(urlHistory instanceof UrlHistory)) throw new TypeError('"urlHistory" is not an "UrlHistory" object');

$.ajax({
url: '/CollateralManagement/Session/AddUrl',
type: 'POST',
success: function (result) {
},
data: { __RequestVerificationToken: $('input[name=__RequestVerificationToken]').val(), model: urlHistory }
});
}

my.addUrl = addUrl;

return my;
})(SessionManager || {});

var UrlHistory = function (area, controller, view, params) {
if (params && !Array.isArray(params)) throw new TypeError('The variable "params" is not null and not an array');

var me = this;

me.Area = area;
me.Controller = controller;
me.View = view;
me.Params = Array.isArray(params) ? params : [];
};

UrlHistory.prototype.coucou = function () {
console.log(this);
};

UrlHistory.prototype.AddParam = function (key, value) {
this.Params.push({ "Key": key, "Value": value });

return this;
};

//I run the code with this exemple:
var uh = new UrlHistory("toto", "tata", "titi");
uh.AddParam("z", "z").AddParam("a", "a");
SessionManager.addUrl(uh);


My object look great:
UrlHistory {Area: "toto", Controller: "tata", View: "titi", Params: Array[2]}

But when I enter in the ajax method I have this error:

Uncaught TypeError: Cannot read property 'push' of undefined

I have tried the same call ajax without to add prototypes, and All is OK.

When the ajax function is run, my 2 methods are called but "this" is "Window" and not "UrlHistory".

Questions:


  • Why methods are called when the post is made?

  • How to post my object?



Thanks

HMR HMR
Answer

The following code will call the function something

var Test = function(){
  this.name="Hello World";
}
Test.prototype.something = function(){
  console.log(".... something has been called",this);
  throw new Error("what is the stack?");
}

jQuery.post("",Object.create(new Test()))

That is because the following line in the jQuery code checks if your object member is a function, if so it will call that function and use the result value.

jQuery uses jQuery.param to serialize the object to http post or get parameters so jQuery.param(new Test()) would throw the same error.

You would like to prevent jQuery from calling the function but I could not find anything in the documentation to override the serialize function but you could add a funciton to your urlHistory type to convert to data:

var urlHistory = function(){
  this.name="Hello World";
}
urlHistory.prototype.something = function(){
  console.log(".... something has been called",this);
  throw new Error("what is the stack?");
};
urlHistory.prototype.toData =  function(){
    var ret = {};
    //this works in your example but if nested objects have functions
    //  it may still fail
    for ( prefix in this ) {
        if(typeof this[ prefix ] !== "function" ){
          ret[ prefix ] = this[ prefix ];
        }
    }
    return ret;
}

console.log("..... working:",jQuery.param((new urlHistory()).toData()))

In your case you can add toData to urlHistory and then in the ajax call do: model: urlHistory.getData()

Comments