The following code works great with a hardcoded array (initialData1), however I need to use jquery .ajax (initialData) to initialize the model and when I do the model shows empty:
$(function () {
function wiTemplateInit(winame, description) {
this.WIName = winame
this.WIDescription = description
}
var initialData = new Array;
var initialData1 = [
{ WIName: "WI1", WIDescription: "WIDescription1" },
{ WIName: "WI1", WIDescription: "WIDescription1" },
{ WIName: "WI1", WIDescription: "WIDescription1" },
];
console.log('gridrows:', initialData1);
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: "{UserKey: '10'}",
url: "WIWeb.asmx/GetTemplates",
success: function (data) {
for (var i = 0; i < data.d.length; i++) {
initialData.push(new wiTemplateInit(data.d[i].WiName,data.d[i].Description));
}
//console.log('gridrows:', initialData);
console.log('gridrows:', initialData);
}
});
var viewModel = function (iData) {
this.wiTemplates = ko.observableArray(iData);
};
ko.applyBindings(new viewModel(initialData));
});
I have been trying to work from the examples on the knockoutjs website, however most all the examples show hardcoded data being passed to the view model.
make sure your "WIWeb.asmx/GetTemplates" returns json array of objects with exact structure {WIName : '',WIDescription :''}
and try using something like this
function wiTemplateInit(winame, description)
{
var self = this;
self.WIName = winame;
self.WIDescription = description;
}
function ViewModel()
{
var self = this;
self.wiTemplates = ko.observableArray();
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: "{UserKey: '10'}",
url: "WIWeb.asmx/GetTemplates",
success: function (data)
{
var mappedTemplates = $.map(allData, function (item) { return new wiTemplateInit(item.WiName, item.Description) });
self.wiTemplates(mappedTemplates);
}
});
}
var vm = new ViewModel();
ko.applyBindings(vm);
If you show us your browser log we can say more about your problem ( Especially post and response ). I prepared you a simple example to show how you can load data with ajax , bind template , manipulate them with actions and save it.
Hope this'll help to fix your issue : http://jsfiddle.net/gurkavcu/KbrHX/
Summary :
// This is our item model
function Item(id, name) {
this.id = ko.observable(id);
this.name = ko.observable(name);
}
// Initial Data . This will send to server and echo back us again
var data = [new Item(1, 'One'),
new Item(2, 'Two'),
new Item(3, 'Three'),
new Item(4, 'Four'),
new Item(5, 'Five')]
// This is a sub model. You can encapsulate your items in this and write actions in it
var ListModel = function() {
var self = this;
this.items = ko.observableArray();
this.remove = function(data, parent) {
self.items.remove(data);
};
this.add = function() {
self.items.push(new Item(6, "Six"));
};
this.test = function(data, e) {
console.log(data);
console.log(data.name());
};
this.save = function() {
console.log(ko.mapping.toJSON(self.items));
};
}
// Here our viewModel only contains an empty listModel
function ViewModel() {
this.listModel = new ListModel();
};
var viewModel = new ViewModel();
$(function() {
$.post("/echo/json/", {
// Data send to server and echo back
json: $.toJSON(ko.mapping.toJS(data))
}, function(data) {
// Used mapping plugin to bind server result into listModel
// I suspect that your server result may contain JSON string then
// just change your code into this
// viewModel.listModel.items = ko.mapping.fromJSON(data);
viewModel.listModel.items = ko.mapping.fromJS(data);
ko.applyBindings(viewModel);
});
})
Related
I have a model created in javascript as follows
function Vehicle() {
this.type = 'Vehicle';
this.data = {
VehicleKey: null
}
};
I have a similar model created in c# as follows
public class Vehicle
{
public string VehicleKey { get; set; }
}
Now I am building an array of VehicleKeys in javascript as follows
function GetVehicleDetails(inputarray) {
var vehicleKeys = [];
for (var i = 0; i < inputarray.length; i++) {
var vehicleObject = new Vehicle();
vehicleObject.data.VehicleKey = inputarray[i].VehicleKey ? inputarray[i].VehicleKey : null;
vehicleKey.push(vehicleObject.data);
}
return vehicleKeys ;
}
I am calling the $.post(url, data) as follows
var objectToSend = GetVehicleDetails(selectedVehicles);
var data = JSON.stringify({
'vehicles': objectToSend
});
$.post(url, data)
.done(function (result) {
if (result) {
download(result, 'VehicleReport.xlsx', { type: 'application/octet-stream' });
console.log("Report created successfully");
}
else {
console.log("Error creating report");
}
}).fail(function (error) {
console.log("Error creating report.");
});
The MVC Controller has a method to accept Vehicles with multiple VehicleKeys coming from javascript
public byte[] CreateVehicleReport(List<Vehicle> vehicles)
{
//Generation of report and pass it back to javascript
}
Here I am able to submit the data in javascript as 10 and 11 for Vehicles but when it catches the c#, the count is coming as 0.
Any help would be greatly appreciated.
$.post is not posted Content-Type json data so you need to use $.ajax
function GetVehicleDetails(inputarray) {
var vehicleKeys = [];
for (var i = 0; i < inputarray.length; i++) {
var vehicleObject = {}; // Set Object
vehicleObject.VehicleKey = inputarray[i].VehicleKey ? inputarray[i].VehicleKey : null;
vehicleKeys.push(vehicleObject);
}
return vehicleKeys;
}
var objectToSend = GetVehicleDetails(selectedVehicles);
$.ajax({ type: 'POST',
url: url,
data: JSON.stringify(objectToSend),
contentType: "application/json",
dataType: 'json',
success: function (data) {
alert('data: ' + data);
},
}).done(function () {
if (result) {
console.log("Report created successfully");
}
else {
console.log("Error creating report");
}
}).fail(function () {
console.log("Error creating report.");
});
C# Method
[HttpPost("CreateVehicleReport")]
public byte[] CreateVehicleReport([FromBody]List<Vehicle> vehicles)
{
return null;
//Generation of report and pass it back to javascript
}
I used a similar approach once but with ajax and it went like this:
fill your array directly with the properties inside your class as object { } make sure the names are exactly the same:
function GetVehicleDetails(inputarray) {
var data_Temp = [];
for (var i = 0; i < inputarray.length; i++) {
var _vehiclekey = inputarray[i].VehicleKey ? inputarray[i].VehicleKey : null;
data_Temp.push({ VehicleKey : _vehiclekey });
});
return data_Temp;
}
var objectToSend = GetVehicleDetails(selectedVehicles);
var JsonData = JSON.stringify({ vehicles: objectToSend });
$.ajax({
type: "POST",
contentType: "application/json",
url: "/controllerName/actionName", //in asp.net using mvc ActionResult
datatype: 'json',
data: JsonData,
success: function (response) {
},
error: function (response) {
console.log(response);
}
});
And the ActionResult in the controller should look like this:
[HttpPost]
public ActionResult Create(List<Vehicle> vehicles)
{
//do whatever you want with the class data
}
I don't know if this is helpful for you but this always works for me and i hope it helps.
I have a view model in knockout as follow. What i intend to achieve here is to make the ajax call into a reusable function as follow (and include it into separate js file).
However, I got the error message showing self.CountryList is not defined. How could this be resolved?
// Working
var ViewModel = function() {
var self = this;
self.CountryList = ko.observableArray([]);
self.LoadCountry = function() {
$.ajax({
url: '/api/MyApi',
type: 'GET',
dataType: 'json',
success(data): {
$.each(data, function (index, value) {
self.CountryList.push(value);
});
}
});
}
}
ko.applyBindings(new LoadCountry());
// Not working
function LoadCountryList() {
$.ajax({
url: '/api/MyApi',
type: 'GET',
dataType: 'json',
success(data): {
$.each(data, function (index, value) {
self.CountryList.push(value);
});
}
});
}
var ViewModel = function() {
var self = this;
self.CountryList = ko.observableArray([]);
self.LoadCountry = function() {
LoadCountryList();
}
}
ko.applyBindings(new LoadCountry());
Your LoadCountryList function in the second version has no concept of the object it should be operating on - ie it has no idea what self is, hence the error. The simple solution is for you to pass the object in when calling the function:
function LoadCountryList(vm) {
$.ajax({
url: '/api/MyApi',
type: 'GET',
dataType: 'json',
success(data): {
$.each(data, function (index, value) {
//reference the parameter passed to the function
vm.CountryList.push(value);
});
}
});
}
var ViewModel = function() {
var self = this;
self.CountryList = ko.observableArray([]);
self.LoadCountry = function() {
//pass ourselves to the function
LoadCountryList(self);
}
}
well clearly self.ContryList does not exist in your external file. One easy way to solve this is to pass in a reference to the appropriate "list" to push values to:
function LoadCountryList(countryList) {
$.ajax({
url: '/api/MyApi',
type: 'GET',
dataType: 'json',
success(data): {
$.each(data, function (index, value) {
countryList.push(value);
});
}
});
}
and in your view model:
var ViewModel = function() {
var self = this;
self.CountryList = ko.observableArray([]);
self.LoadCountry = function() {
LoadCountryList(self.CountryList);
}
}
This is how I have my page set up, but no data is being displayed, and I'm not sure why:
JavaScript/knockout:
var getList = function () {
Ajax.Get({
Url: ...,
DataToSubmit: {id: properties.Id },
DataType: "json",
OnSuccess: function (roleData, status, jqXHR) {
bindModel(roleData);
}
});
};
// Binds the main ViewModel
var bindModel = function (data) {
var _self = viewModel;
ko.applyBindings(viewModel, $('#ListView')[0]);
};
var viewModel = {
ListRoleTypes: ko.observableArray([]),
.....
};
var roleViewModel = function (data) {
var _self = this;
_self.ContentRole = ko.observable(data.ContentRole);
_self.RoleName = ko.observable(data.RoleName);
_self.RoleRank = ko.observable(data.RoleRank);
_self.UserCount = ko.observable(data.UserCount);
};
This is my View page:
<div data-bind="foreach: ListRoleTypes">
<span data-bind="text: RoleName"></span>
</div>
Any thoughts on where I am going wrong?
you are calling bindmodel and passing in the roledata, but then in bindmodel, you dont do anything with it.
Ajax.Get({
Url: ...,
DataToSubmit: {id: properties.Id },
DataType: "json",
OnSuccess: function (roleData, status, jqXHR) {
bindModel(roleData);
}
});
};
// Binds the main ViewModel
var bindModel = function (data) {
// need to do something with viewmodel to handle the passed in data
viewmodel.initialize(data);
ko.applyBindings(viewModel, $('#ListView')[0]);
};
I have this view model that is getting data from entity famework. i am able to convert it successfully from JSON to an array but it's not observable. I have tried creating a model that has observable properties and then populating with a for each but that didn't seem to work . I also tried using ko.mapping.fromJSON that seemed to work ok on the service side but its always empty on the view.
function(logger, system, router, employeeService) {
var EmployeeDetails = ko.observableArray([]);
Activate Function -
var activate = function () {
return GetEmployeeDetails(),GetTermList();
};
var vm = {
activate: activate,
FindID: ko.observable(),
EmployeeDetails: EmployeeDetails
}
};
function GetEmployeeDetails() {
return employeeService.getemployeeDetails(EmployeeDetails);
}
//This is the function in my employeeService class
var getEmployeedetails = function(employeeDetailsOb) {
var jsonfromServer;
$.ajax({
type: "POST",
dataType: "json",
url: "/api/employee/getAllDetails/",
data: '{}',
success: function(data) {
jsonfromServer = $.parseJSON(data);
},
error:
{ //error stuff})
Return employeeDetailsOb(jsonFromServer);
}
Assuming you are trying to return EmployeeDetails() object from getEmployeeDetails(...) before you actually successfully return from that call, try putting your vm.EmployeeDetails initialization inside your sucess handler:
success: function(data) {
jsonfromServer = $.parseJSON(data);
for (var i = 0; i < jsonFromServer.list.length; ++i)
{
vm.EmployeeDetails.push(jsonFromServer.list[i]);
}
},
I think once EmployeeDetails has been set as an observable array you can just set your observable array data like this:
vm.EmployeeDetails(jsonfromServer.list);
I'm pretty new to Backbone and I've been trying to create autocomplete functionality with it, fed by an ASMX webservice. The issue I seem to have is whilst my webservice returns in JSON (after a painful battle with it), it wraps the response in a 'd' (dataset). How do I get the view to understand this and get at the correct data?
Here is my code:-
var Airline = Backbone.Model.extend({
initialize: function () {},
defaults: {
name: 'Airline Name',
rating: 50,
icon: '/blank.png'
}
});
var AirlineCollection = Backbone.Collection.extend({
model: Airline,
contentType: "application/json",
url: '/ControlTower/public/runway.asmx/all-airlines',
parse: function (response) {
return response;
}
});
var SelectionView = Backbone.View.extend({
el : $('#airline'),
render: function() {
$(this.el).html("You Selected : " + this.model.get('AirlineName'));
return this;
},
});
var airlines = new AirlineCollection();
airlines.fetch({async: false, contentType: "application/json" });
var airlineNames = airlines.pluck("AirlineName");
$("#airline").autocomplete({
source : airlineNames,
minLength : 1,
select: function(event, ui){
var selectedModel = airlines.where({name: ui.item.value})[0];
var view = new SelectionView({model: selectedModel});
view.render();
}
});
Can anyone see what I'm doing wrong? I've been sitting here for too long now!
Help is appreciated ;)
What about in your AirlineCollection:
parse: function (response) {
return response.d;
}
This works for me
In AirlineCollection
parse: function (response) {
var data = (typeof response.d) == 'string' ? eval('(' + response.d + ')') : response.d;
return data;
}