Knockout return observable array from json - javascript

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

Related

Calling an ASP.NET MVC-view via ajax does not work

I am trying to call a view with an ajax-Call, passing an Id to the Controller-method. The Id is passed, everything is fine until I call the view in the return-Statement. Nothing happens.
$("#btnCreatePackage").click(function () {
var workflowId = $("#workflowId")[0].value;
$.ajax({
url: '#Url.Action("Create", "package")',
type: 'get',
data: { id: workflowId },
success: function (data) {
return data;
},
timeout: 500
});
});
public ActionResult Create(int id) {
IList < Workflow > workflows = WorkflowService.GetWorkflowList();
ModifyPackageViewModel vm = new ModifyPackageViewModel
{
Package = null,
Workflow = workflows.SingleOrDefault(x => x.Id == id),
Workflows = workflows,
Hosts = ScalingService.GetHostList(),
SelectedHostNames = new List<string>(),
Factor = 1
};
if (!vm.SelectedHostNames.Any()) {
if (vm.Hosts.Any()) {
vm.SelectedHostNames.Add(vm.Hosts.First().Name);
}
}
return View(vm);
}
The curious thing is, if i#m calling the view via #Url.Action without passing the Id with the following code, it works.
<a href="#Url.Action("Create")">
<div class="submenu-item add">
neues paket anlegen
</div>
</a>
public ActionResult Create() {
IList<Workflow> workflows = WorkflowService.GetWorkflowList();
ModifyPackageViewModel vm = new ModifyPackageViewModel
{
Package = null,
Workflow = workflows.FirstOrDefault(),
Workflows = workflows,
Hosts = ScalingService.GetHostList(),
SelectedHostNames = new List<string>(),
Factor = 1
};
if (!vm.SelectedHostNames.Any()) {
if (vm.Hosts.Any())
{
vm.SelectedHostNames.Add(vm.Hosts.First().Name);
}
}
return View(vm);
}
In both cases the Controller-method is called, goes through to the end without errors, in the first case nothing happens, in the second case everything is fine.
Anyone any ideas??????
Thanks, daniel
You can't return the data from an ajax call. You can store it in a variable declared outside, or do something inside your success handler.
This works just as well with your success handler (success: function(data) ...). The main thing to remember is the scope of the data that is returned from your controller.
EX:
var outsideVariable; // You can store the data in here for later if you need to
$.ajax({
url: '#Url.Action("Create", "Package")',
type: 'GET',
data: { id: workflowId }
}).fail(function (data) {
// Fail handler
}).done(function (data) {
// Success, Do Something
YourFunctionThatProcessesData(data);
// Or store the data into a variable that has outside scope
outsideVariable = data;
}).always(function () {
//Do this no matter what
});
function YourFunctionThatProcessesData(data)
{
// do stuff with the data
}
At least I fixed it, I did not need an ajax-Call, instead I just used this:
$("#btnCreatePackage").click(function() {
var workflowId = $("#workflowId")[0].value;
window.location.href = '#Url.Action("Create", "package")/' + workflowId;
});
It can be that simple........

jquery ajax store variable and then retrieve later on

Hi i am using jquery and ajax to retrieve the user id of the logged in user, Im saving this into a variable as I want to be able to do some logic with it later on. however I am having trouble accessing it. My code is below:
$(document).ready(function () {
var taskBoard = {
fetch: function (url, data) {
$('.loading-icon').fadeIn();
$('.task_board').addClass('loading');
$.ajax({
url: url,
async: true,
dataType: 'json',
data: data,
type: 'POST',
success: function (json) {
$('.loading-icon').fadeOut();
$('#task_board').html($(json.data.taskBoard));
$('.task_board').removeClass('loading');
$('.update-results').hide();
} // end success
}); //end ajax
}, //end fetch function
authUser: function (url, data) {
$.ajax({
url: url,
async: true,
dataType: 'json',
data: data,
type: 'POST',
success: function (json) {
$.each($(json), function (index, item) {
taskBoard.storeUser(item.id);
});
} // end success
}); //end ajax
}, //end authUser function
storeUser: function (param) {
var authUserId = param;
return param;
// if I do an alert here the correct user id is returned.
},
} //end var taskBoard
//However if I do an alert here outside of the var taskBoard I get an undefined.
alert(taskBoard.storeUser());
});
Any ideas how I can get this globally assigned variable outside of this function?
change this
storeUser: function (param) {
var authUserId = param;
return param;
// if I do an alert here the correct user id is returned.
},
change to this:
authUserId : null,
storeUser: function (param) {
if (param)
{
this.authUserId = param;
}
return this.authUserId;
},
Now the var authUserId will be stored as a property in the taskBoard object.
When param is undefined it will return the value unupdated if not it will update it first and then returns it.
A more elegant solution would be to use Object.defineProperty here.
Delete the storeUser property and after the declaration of the taskBoard object add this:
Object.defineProperty(taskBoard, "storeUser", {
get : function(){ return this.StoreUserVar; },
set : function(value){ this.StoreUserVar = value; }
});
Now you can assign the userid with:
taskBoard.storeUser = item.id;
//-------- taskBoard object
success: function (json) {
$.each($(json), function (index, item) {
taskBoard.storeUser = item.id;
doOtherFunction();
});
//--------
function doOtherFunction()
{
//the callback function fired from the success.
alert(taskBoard.storeUser); //this will alert with the value set.
}
Well if you need a global variable then declare that variable before the document.ready, since variables defined in this function are only valid in this function
Javascript Scope Examples

jQuery autocomplete for json data

I am returning array of strings from controller to ajax call. trying to set to textbox those values. in textbox it is not populating. but I can see data in success method.
[HttpGet]
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public JsonResult GetWorkNamesAutoPoplate(string companyName)
{
...
var newKeys = companyNameslst.Select(x => new string[] { x }).ToArray();
var json = JsonConvert.SerializeObject(newKeys);
return Json(json, JsonRequestBehavior.AllowGet);
}
JS
$(document).on('change', '[name="FindCompanyName"]', function () {
$('[name="FindCompanyName"]').autocomplete({
source: function (request, response) {
$.ajax({
url: "GetWorkNamesAutoPoplate",
type: "GET",
dataType: "json",
data: { companyName: $('[name="FindCompanyName"]').val() },
success: function (data) {
alert(JSON.stringify(data));
response($.map(data, function(item) {
console.log(item);
return {
value: item
}
}));
}
});
},
messages: {
noResults: "", results: ""
}
});
});
alert(JSON.stringify(data)); display like this.
How to populate this data in textbox
The return type of your json is an array of arrays, i think you should return it as an array
var newKeys = companyNameslst.ToArray();
also, your data are serialized twice,
one from line,
var json = JsonConvert.SerializeObject(newKeys);
and second time from JsonResult action filter
return Json(json, JsonRequestBehavior.AllowGet);
sending json data like,
return Json(newKeys, JsonRequestBehavior.AllowGet);
instead of
var json = JsonConvert.SerializeObject(newKeys);
return Json(json, JsonRequestBehavior.AllowGet);
should work.
hope this helps.
This may resolve your issue :
success: function (data) {
alert(JSON.stringify(data));
if (data != null) {
response(data.d);
}
}
Also this link might help you to get some information :How to use source: function()... and AJAX in JQuery UI autocomplete

Passing an array of Javascript classes to a MVC controller?

I am trying to pass an array of services to my controller.
I've tried a bunch of different ways to get it work, serializing the data before going to controller, serializing each service, only thing that seems to work is changing the controller parameter to string and serializing array, then using JsonConvert, but I'd rather not do that.
With the specified code, I am getting the correct number of items in the List, but they all contain a service id with an empty guild, and service provider id is null.
Any ideas?
Javascript
function ServiceItem() {
this.ServiceProviderID = 'all';
this.ServiceID = '';
}
var selecteditems= (function () {
var services = new Array();
return {
all: function() {
return services;
},
add: function(service) {
services.push(service);
}
};
})();
var reserved = [];
$.each(selecteditems.all(), function(index, item){
reserved.push({ ServiceID: item.ServiceID, ServiceProviderID: item.ServiceProviderID});
});
getData('Controller/GetMethod', { items: reserved }, function(result) {
});
var getData = function (actionurl, da, done) {
$.ajax({
type: "GET",
url: actionurl,
data: da,
dataType: "json",
async: true,
success: function (d) {
if (typeof (done) == 'function') {
var str = JSON.stringify(d);
done(JSON.parse(str));
}
}
});
};
Controller
public JsonResult GetMethod(List<CustomObject> items)
{
}
Custom Object
public class CustomObject
{
public Guid ServiceID {get;set;}
public Guid? ServiceProviderID {get;set;}
}
Set the content-type and use POST instead of GET (as it is a list of complex type objects). mark your action with HttpPost attribute too.
See if this works:-
$.ajax({
type: "POST",
url: actionurl,
data: JSON.stringify(da),
dataType: "json",
contentType: 'application/json',
async: true,
success: function (d) {
if (typeof (done) == 'function') {
var str = JSON.stringify(d);
done(JSON.parse(str));
}
}
});

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