calling ajax function from knockout value undefined - javascript

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);
}
}

Related

Unable to update class variable after ajax call

After getting two integer upon the ajax request has been completed, this.N and this.M are not getting set by storeDims() even if the dims has correctly been decoded. So it seems that I cannot acces this.N and this.M declared in the constructor.
This is the code
class MapModel {
constructor() {
this.N; // need to initialize this after an ajax call
this.M;
this.seats = new Array();
this.remote_seats = new Array();
}
init(callback) {
let _this = this;
$.when(
_this.getDims(),
_this.getSeats(),
).then(this.initMap(callback))
}
initMap(callback) {
console.log(this.N); // prints undefined
console.log(this.M); // this as well
callback(this.N, this.M, this.seats);
}
getDims() {
let _this = this;
$.ajax({
url: 'src/php/data.php',
type: 'POST',
data: {action: 'getDims'},
success: function (result) {
let dims = JSON.parse(result); // dims[0] = 10, dims[1] = 6
_this.storeDims(dims);
}
});
}
storeDims(dims) {
console.log(dims);
this.N = parseInt(dims[0]);
this.M = parseInt(dims[1]);
console.log(this.N);
console.log(this.M);
}
getSeats() {
let _this = this;
$.ajax({
url: 'src/php/data.php',
type: 'POST',
data: {action: 'getSeats'},
success: function (result) {
let seats = JSON.parse(result);
_this.storeSeats(seats);
}
});
}
storeSeats(seats) {
this.remote_seats = seats;
console.log(this.remote_seats);
}
}
You need to return the ajax promises from the getDms and getSeats functions
getDims() {
let _this = this;
return $.ajax({
url: 'src/php/data.php',
type: 'POST',
data: {action: 'getDims'},
success: function (result) {
let dims = JSON.parse(result); // dims[0] = 10, dims[1] = 6
_this.storeDims(dims);
}
});
}
you can even pass the values directly to the initMap
init(callback) {
let _this = this;
$.when(
_this.getDims(),
_this.getSeats()
).then(function(dims,seats) {_this.initMap(dims,seats,callback)})
}
initMap(dimsRaw,seatsRaw, callback) {
let dims = JSON.parse(dimsRaw);
console.log(dims[0]);
console.log(dims[1]);
callback(dims[0], dims[1], this.seats);
}
The init promise callback is being called on the chain declaration, try adding a function wrapper:
init(callback) {
let _this = this;
$.when(
_this.getDims(),
).then(function() {_this.initMap(callback)})
}

Dynamically send parameter in ajax-chosen

I am new to Jquery world.
I have these following codes:
$target.ajaxChosen({
type: 'GET',
url: '<s:url action="getFilterValueJSON" namespace="/cMIS/timetable"></s:url>?filterKey='+keyword,
dataType: 'json',
jsonTermKey: 'filterWord'
}, function (data) {
var terms = [];
mydata = data.valueMap;
$.each(mydata, function (i, val) {
terms.push({ value: i, text: val });
});
return terms;
});
It seems the variable 'keyword' does not dynamically changed its value. The value for 'keyword' comes from an element with on change event. Would someone enlighten me about this on how to solve this? Thanks in advance.
its better you compose your url object just before call
function onclick(keyword)
{
var url = '<s:url action="getFilterValueJSON" namespace="/cMIS/timetable"></s:url>?
filterKey='+keyword;
ajaxCall(url);
}
function ajaxCall(url)
{
$target.ajaxChosen({
type: 'GET',
url: url,
dataType: 'json',
jsonTermKey: 'filterWord'
}, function (data) {
var terms = [];
mydata = data.valueMap;
$.each(mydata, function (i, val) {
terms.push({ value: i, text: val });
});
return terms;
});
}

data-bind not displaying data in view page

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]);
};

javascript oop multiple classes

Hi Im having problems with javascript! i have main.js and Model.js. Model.js is a javascript oop class in need to access its functions in main.js how do i do that? I keep getting an error that Model is not defined. Are there tools needed for this to work or something is wrong in the code?
Model.js
Model = {};
Model.init = function() {
alert("model");
}
Model.getList = function(){
var list;
$.ajax(
{
url:'???',
type: 'GET',
dataType: 'json',
success: function(data)
{
list=data;
}
error: function(data)
{
alert("error");
}
});
return list;
}
main.js
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
var testins=new Model();
var list=Model.getList();
alert("result: "+testins);
}
I really could use some help.
so I tried MrCode approach and for experimental reasons put the code in one file because main.js still could not access the Model.js file.
main.js
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
alert("aaa"); //first
var testins=new Model();
var list=testins.getList();
alert("result: "+testins); // third
alert("list"+list); //fourth
}
function Model()
{
this.init = function()
{
alert("Model");
}
this.getList = function()
{
var list;
$.ajax(
{
url:'??',
type: 'GET',
dataType: 'json',
success: function(data)
{
list=data;
alert("success"+list); //fifth
},
error: function(data)
{
alert("error");
}
});
alert("success"+list); //second
return(list);
}
}
but following the alerts i see the that the $.ajax part is done last.
Do
function Model() { // this is the "constructor"
}
And replace
Model.init = function() {
by
Model.prototype.init = function() { // provide the function to all instances
(and the same for getList)
This will enable
you to call new Model()
the init function to be inherited by the objects you create with new Model().
Use it like this :
var testins=new Model(); // create an instance
var list=testins.getList(); // call the instance method
You may be interested by this MDN document about prototype and inheritance.
function Model()
{
// define public methods
this.init = function()
{
alert("Model");
}
this.getList = function()
{
var list;
$.ajax(
{
url:'???',
type: 'GET',
dataType: 'json',
success: function(data)
{
list=data;
}
error: function(data)
{
alert("error");
}
});
return list;
}
}
var testins = new Model(); // create an instance of Model()
var list = testins.getList(); // call its method

How to initialize knockoutjs view model with .ajax data

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);
});
})

Categories

Resources