I have been using knockout.js for a while now, and haven’t encountered this problem before. Usually, when I try to push a new js object to an observableArray, it works without an issue, but for some reason, this time around I’m getting this error:
TypeError: self.Students.push is not a function
Here is a snippet of my code:
window.ApiClient = {
ServiceUrl: "/api/students",
Start: function () {
var viewModel = ApiClient.ViewModel(ngon.ClientViewModel);
ko.applyBindings(viewModel);
viewModel.get();
}
};
ApiClient.ViewModel = function(data) {
var self = this;
ko.mapping.fromJS(data, {}, this);
this.get = function (id) {
if (id == undefined) {
return ApiClient.Service.get(self.PageSize(), self.PageNumber(), function (data) {
self.Students(data);
});
}
}
this.post = function () {
return ApiClient.Service.post(self.DetailedStudent, function (data) {
self.Students.push(data);
});
}
return this;
}
ApiClient.Service = function () {
var _get = function (pageSize, pageNumber, callback) {
sv.shouldShowLoading = false;
var queryParams = String.format("?pageSize={0}&pageNumber={1}", pageSize, pageNumber);
$.ajax(ApiClient.ServiceUrl + queryParams, {
dataType: "json",
type: "get",
success: callback
});
}
var _post = function (student, callback) {
$.ajax(ApiClient.ServiceUrl, {
data: ko.mapping.toJSON(student),
type: "post",
contentType: "application/json; charset-utf-8",
statusCode: {
201 /*Created*/: callback,
400 /*BadRequest*/: function (jqxhr) {
var validationResult = $.parseJSON(jqxhr.responseText);
alert(jqxhr.responseText);
}
}
});
}
return {
get: _get,
post: _post
};
}();
$(document).ready(function () {
ApiClient.Start();
});
My student object is a very simple C# object that has Id, FirstName, LastName. The get() function works without any issues, it’s just the callback function from the post() that cannot push the resulting data. Also, the data being returned back from the server looks correct:
{"Id":"rea","FirstName":"asdf","MiddleName":null,"LastName":"rrr"}
I solved this! It’s because the initial viewModel, when being instantiated by the page’s view model object had ‘null’ for its Students property.
knockout.js requires non-null values for all fields that are to be auto mapped.