Post data from Knockout to Controller using Ajax - javascript

I'm getting null for the controller parameter. I am posting data as I can see it in Chrome Developer tools. I have a Person model in MVC that matches the Person model below. This is my ViewModel :
function Person(data) {
this.FirstName = ko.observable(data.FirstName);
this.LastName = ko.observable(data.LastName);
this.Id = ko.observable(data.Id);
this.fullName = ko.computed(function () {
return this.FirstName() + " " + this.LastName();
}, this);
}
function PersonViewModel() {
var self = this;
self.people = ko.observableArray([]);
$.getJSON("/api/person/getpeople", function (allData) {
var mappedTasks = $.map(allData, function (item) { return new Person(item) });
self.people(mappedTasks);
});
self.save = function(){
$.ajax("/api/person/updateperson", {
data: ko.toJSON({ people: self.people }),
type: "post", contentType: "application/json",
success: function (result) { alert(result) }
});
}
}
ko.applyBindings(new PersonViewModel);
API controller:
[HttpPost]
public bool UpdatePerson(List<Person> person)
{
return mgr.UpdatePerson(person);
}

You need to make sure that the service parameter's names match up with what you're passing.
self.save = function(){
$.ajax("/api/person/updateperson", {
data: ko.toJSON({ person: self.people }),
type: "post", contentType: "application/json",
success: function (result) { alert(result) }
});
}

Related

view model function is not a function error in knockout

I have this view model,
define(['text!./form.html', 'knockout', '../../home', '../../users'],
function(template, ko,homeModel,userModel) {
function registerUserViewModel() {
var self = this;
...
self.registerUser = function(){
...
$.ajax({
url: 'server/registerUser.php',
type: 'post',
data: {"data":credentials},
success: function (result) {
if(result == "Successful"){
homeModel.viewModel.addUser("Jun","5:30");
}else{
alert(result);
}
}
});
}
return self;
}
return {
viewModel: registerUserViewModel,
template: template
};
});
Here is my homeViewModel,
define(["knockout", "text!./home.html", "../../users"],
function (ko, homeTemplate, userModel) {
function homeViewModel(params) {
var self = this;
...
self.users = ko.observableArray([]);
$.ajax({
url: 'server/getUsers.php',
type: 'post',
data: {"data":id},
success: function (result) {
var row = JSON.parse(result)
for(var i=0;i<row.length;i++){
self.users.push(new userModel.userModel(row[i]["name"],row[i]["time"],row[i]["id"]));
}
}
});
self.addUser = function(name,time){
self.users.push(new userModel.userModel(name,time));
}
return self;
}
return { viewModel: homeViewModel, template: homeTemplate };
});
When I go to the page,
There is an error,
homeModel.viewModel.addUser is not a function.
but I assigned a function to self.addUser. I tried homeModel.addUser but still not working.
Is there any other way to simply add a new userModel to self.users array?

500 error with knockout delete

I am getting a 500 error when I try and delete an item in my list using ajax.
From using the console on Chrome combined with Fiddler, a null reference on the Id is the issue. Debugging through Chrome's console shows that the announcement object does have an Id.
I was under the impression 500 errors came from the server, but I have a break point on the function path it's calling and not getting hit.
Is there anything that is staring me in the face as to why this would be setting the announcement.Id to null?
controller:
public JsonResult DeleteAnnouncement(int Id)
{
if(repository.DeleteAnnouncement(Id))
{
return Json(repository.GetAllAnnouncements(), JsonRequestBehavior.AllowGet);
}
return Json(null);
}
repository:
public bool DeleteAnnouncement(int Id)
{
var model = (from a in db.DbAnnouncement
where a.Id == Id
select a).SingleOrDefault();
if (model.Id != 0)
{
db.DbAnnouncement.Remove(model);
db.SaveChanges();
return true;
}
else
{
return false;
}
}
js script:
<script type="text/javascript">
function AnnouncementViewModel() {
//Make the self as 'this' reference
var self = this;
//Declare observable which will be bind with UI
self.Id = ko.observable("");
self.Title = ko.observable("");
self.Details = ko.observable("");
self.DTCreated = ko.observable("");
self.LastUpdated = ko.observable("");
self.CreatedUser = ko.observable("");
self.UpdatedUser = ko.observable("");
self.VersionNum = ko.observable("");
self.StartDT = ko.observable("");
self.ExpiryDT = ko.observable("");
self.Enabled = ko.observable("");
self.GroupID = ko.observable("");
self.URLLink = ko.observable("");
var Announcement = {
Id: self.Id,
Title: self.Title,
Details: self.Details,
DTCreated: self.DTCreated,
LastUpdated: self.LastUpdated,
CreatedUser: self.CreatedUser,
UpdatedUser: self.UpdatedUser,
VersionNum: self.VersionNum,
StartDT: self.StartDT,
ExpiryDT: self.ExpiryDT,
Enabled: self.Enabled,
GroupID: self.GroupID,
URLLink: self.URLLink
};
self.Announcement = ko.observable();
self.Announcements = ko.observableArray(); // list of announcements
// Delete announcement
self.delete = function (Announcement) {
if (confirm('Are you sure to Delete "' + Announcement.Title + '"?')) {
$.ajax({
url: '#Url.Action("DeleteAnnouncement","Announcement")',
cache: false,
type: 'POST',
contentType: 'application/json; charset=utf-8',
//data: ko.toJSON(Announcement.Id),
data: {Id: Announcement.Id},
success: function (data) {
self.Announcements.remove(Announcement);
alert("Record Deleted Successfully");
}
}).fail(
function (xhr, textStatus, err) {
alert(err);
});
}
}
}
$(document).ready(function () {
var viewModel = new AnnouncementViewModel();
ko.applyBindings(viewModel);
});
You are using ajax contentType as Json but not really sending a json object to server. Use
data: JSON.stringify({ Id: Announcement.Id() }),
and decorate your mvc action with [HttpPost]
[HttpPost]
public JsonResult DeleteAnnouncement(int Id)
{}

Unable to bind function to button click

I have a viewModel with a function
function resetForm(){
loanSystem("lis");
status("");
processor("");
fileType("funded");
orderDate("");
loanNumber("");
team("");
borrower("");
tracking("");
};
And a button on page with
<button type="reset" data-bind="click: resetForm">Reset</button>
But I am getting error:
Unable to process binding "click: function(){ return resetForm}. resetForm is not defined.
But I know my resetForm() works because it is called in my init function and if I change values in my resetForm() it show on initial page load. Any ideas?
var homeViewModel = (function () {
var loanSystem = ko.observable("lis");
var status = ko.observable("");
var processor = ko.observable("");
var fileType = ko.observable("funded");
var orderDate = ko.observable("");
var loanNumber = ko.observable("");
var team = ko.observable("");
var borrower = ko.observable("");
var tracking = ko.observable("");
var isLoanSystem = ko.computed(function () {
return (loanSystem() == "lps");
});
var isCalendar = ko.computed(function () {
return (isLoanSystem() && fileType() == "cancelled");
});
function resetForm(){
loanSystem("lis");
status("");
processor("");
fileType("funded");
orderDate("");
loanNumber("");
team("");
borrower("");
tracking("");
};
function submitFileInformation() {
if (!ValidInputs()) {
return;
}
var fileData = {
loanSystem: loanSystem(),
status: status(),
processor: processor(),
fileType: fileType(),
orderDate: orderDate(),
loanNumber: loanNumber(),
team: team(),
borrower: borrower(),
tracking: tracking()
};
$.ajax({
type: "POST",
url: "/ComplianceProcessing/Ajax.ashx",
data: JSON.stringify(fileData),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(data) {
if (data === false) {
alert("There was an error writing the file to the database.");
return;
}
alert('Data has been successfully saved.');
resetForm();
},
failure: function() {
alert('Failure');
}
});
}
return {
init: function() {
resetForm();
},
loanSystem: loanSystem,
isLoanSystem: isLoanSystem,
status: status,
processor: processor,
fileType: fileType,
isCalendar: isCalendar,
orderDate:orderDate,
loanNumber: loanNumber,
team: team,
borrower: borrower,
tracking: tracking
};
})();
Your resetForm is not exprosed from your viewmodel which makes it esentally private so Knockout cannot find it.
The solution is very easy, just include the resetForm in your returned object (which is your "public API"):
return {
init: function() {
resetForm();
},
loanSystem: loanSystem,
isLoanSystem: isLoanSystem,
status: status,
processor: processor,
fileType: fileType,
isCalendar: isCalendar,
orderDate:orderDate,
loanNumber: loanNumber,
team: team,
borrower: borrower,
tracking: tracking,
resetForm: resetForm //add this line
};

Posting Array and Form Data to Controller - MVC Ajax

I've got an array of Objects in jQuery:
function customersList() {
this.selectedCustomers = [];
}
function customerObject(customerId, bookingId) {
this.customerId = customerId;
this.bookingId = bookingId;
}
I need to post this to my Controller:
[HttpPost]
public ActionResult CreateMultipleCasesFormPost(CreateMultipleCasesModel model)
{
return PartialView("_CreateMultipleCases", model);
}
My ViewModel:
public class CreateMultipleCasesModel
{
[Display(Name = "Selected Customers")]
public List<CustomerList> Customers { get; set; }
I need to pass the Array from jQuery and the Data from this Form to my Controller (My View Model contains other properties):
$('#createMultipleCasesForm')
This is my Post Form jQuery Code:
$('#createMultipleCasesBtn').click(function () {
var btn = $(this);
var mUrl = btn.data('actionurl');
var formModel = $('#createMultipleCasesForm').serializeArray();
var customerList = customersList.selectedCustomers();
var requestData = {
model: formModel,
Customers: customerList
};
var sData = JSON.stringify(requestData);
$.ajax({
url: mUrl,
type: 'POST',
dataType: 'json',
contentType: 'application/json; charset=utf-8',
data: sData,
success: function (response) {
debugger;
},
error: function (response) {
$('#ErrorMessage').html('<span class="icon black cross"></span>' + response.Message);
}
});
});
My Model from jQuery is not Binding either the Array of Customer Objects or the Form, What am I doing wrong here?
EDIT
What happens when I post Back my Form:
I found a solution this did the trick for me:
$('#createMultipleCasesBtn').click(function () {
var btn = $(this);
var mUrl = btn.data('actionurl');
var formModel = $('#createMultipleCasesForm').serializeObject();
formModel['Customers'] = customersList.selectedCustomers;
var sData = JSON.stringify(formModel);
$.ajax({
url: mUrl,
type: 'POST',
dataType: 'json',
contentType: 'application/json; charset=utf-8',
data: sData,
success: function (response) {
},
error: function (response) {
$('#ErrorMessage').html('<span class="icon black cross"></span>' + response.Message);
}
});
});
This Function Below Used from Answer Here: Convert form data to JavaScript object with jQuery
$.fn.serializeObject = function () {
var o = {};
var a = this.serializeArray();
$.each(a, function () {
if (o[this.name] !== undefined) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else {
o[this.name] = this.value || '';
}
});
return o;
};

knockout.js observableArray is not recognized as a function

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.

Categories