Define json specific field is declared or not - json

I have Asp.Net Mvc4 application. In one Action method I have conditional process that return different json result as follows:
if(true)
{
return Json(new { count = cartItm.ProductCount, total = cartItm.TotalAmount });
}
else
{
return Json(new
{
thumb = item.ThumbnailPhoto,
productName = item.Name,
itemCount = cartItem.ProductCount,
itemTotal = cartItem.TotalAmount,
productTotal = cart.TotalAmount,
productCount = cart.CartItems.Sum(items=>items.ProductCount)
});
}
In jquery click event I can't define which json is returned. I write if condition as follows but get wrong result.
success: function (data) {
if (data.thumb != null) {//some operations }
else{//some operations }
Perhaps it is very easy problem, but I am new with json. Please help me.
thanks for reply

Check for "undefined" instead
success: function (data) {
if (typeof data.thumb !== "undefined") {//some operations }
else{//some operations }
Because item.ThumbnailPhoto on your server may be null. If this is the case, your check will fail.

Try this,
success: function (data) {
if (data && data.thumb) {//some operations }
else{//some operations }
}

The problem might be because you don't have data.thumbs in your first json, in your Action,
if(true)
{
return Json(new { flag = 1, count = cartItm.ProductCount, total = cartItm.TotalAmount });
}
else
{
return Json(new
{
flag = 2,
thumb = item.ThumbnailPhoto,
productName = item.Name,
itemCount = cartItem.ProductCount,
itemTotal = cartItem.TotalAmount,
productTotal = cart.TotalAmount,
productCount = cart.CartItems.Sum(items=>items.ProductCount)
});
}
in your view :
success: function (data) {
if (data.flag == 1) {//some operations }
elseif (data.flag == 2) {//some operations }
didnt check the code, but this must work.

Related

ionic: I have a scope variable empty from a stringified json

I'm trying to filter a JSON result from a SQLite query. The filter works when I use JSON directly, but it doesn't when I use the query from the service. Then, the $scope.arrayme just appears as empty.
Where is the error? Thank you!
This is the service:
getSubtipos: function() {
var query = "SELECT subtipos.idsubtipo, subtipos.tipos_idtipo, subtipos.nombre, subtipos.icon, subtipos.val FROM subtipos";
var arraySubtipos = [];
$cordovaSQLite.execute(db, query, []).then(function(res) {
if(res.rows.length > 0) {
for(var i = 0; i < res.rows.length; i++) {
arraySubtipos.push(res.rows.item(i));
}
} else {
console.log("No results found");
}
}, function (err) {
console.error("ERROR: " + err.message);
}).finally(function() {
arraySubtipos = JSON.stringify(arraySubtipos);
});
return arraySubtipos;
}
This is the controller:
.controller('MenuSubtiposCtrl', function($scope, $filter, miJson, $stateParams, $cordovaSQLite){
var arrayme = JSON.stringify(miJson.getSubtipos());
$scope.arrayme = $filter("filter")(JSON.parse(arrayme), {tipos_idtipo: $stateParams.foo});
})
And this is the state:
.state('app.menusubtipos', {
url: "/menusubtipos/:foo",
views: {
'menuContent': {
templateUrl: "templates/menuSubtipos.html",
controller: "MenuSubtiposCtrl"
}
}
})
There may be more problems than what I've immediately noticed, but I have have noticed that you're returning a variable within your getSubtipos function before it's set.
The $cordovaSQL.execute() function is an asyncronous function. As a result, you are returning arraySubtipos before it's set.
A better way to do this would be within getSubtipos to do the following:
var arraySubtipos = [];
return $q.when($cordovaSQLite.execute(db, query, [])
.then(function(res) {
if(res.rows.length > 0) {
for(var i = 0; i < res.rows.length; i++) {
arraySubtipos.push(res.rows.item(i));
}
} else {
console.log("No results found");
}
return JSON.stringify(arraySubtipos);
}));
// Then, within your controller, do the following:
.controller('MenuSubtiposCtrl', function($scope, $filter, miJson, $stateParams, $cordovaSQLite){
miJson.getSubtipos()
.then(function(arrayMe) {
// No need to stringify it again
$scope.arrayme = $filter("filter")(JSON.parse(arrayme), {tipos_idtipo: $stateParams.foo});
})
.catch(function(error) {
// Handle the error here
});
var arrayme = JSON.stringify(miJson.getSubtipos());
});
I'm also a little suspicious about your use of JSON.stringify and JSON.parse. It's likely that they're not needed, but without knowing the format of your data, I've left that as is.

Unable to dynamically load Json Arrays from JSP to a Jstree

I was trying to make a simple LDAP client to just retrieve the data from an LDAP server. I am returning array of JSON objects from the JSP. On click of any value I will get some data from online server. I am able to load the first set of array into a tree. The arrays got in the next step dont get attached to the JSTree. My codes:
function getGroupsStructure(id) {
console.log("in getGroupsStructure-->");
var paramId = "";
if(id == '') {
console.log("in if-->");
paramId = "c=de";
} else {
console.log("in else-->");
paramId = id;
}
var params = {
"DN" : paramId,
};
console.log("params-->",params);
var getGroupsStructureForUserService = service(webURL + "sendingValues/getGroupsStructureForUser",params,"POST");
getGroupsStructureForUserService.success(function(data) {
console.log("in success-->dta-->",data);
if(data.errorCode == '0') {
console.log("in error code 0-->dta-->",data.treeData);
$('.treeNode').jstree({
'core': {
'data': function (obj, cb) {
cb.call(this,
data.treeData);
}
}
});
console.log("Tree Created...");
} else {
console.log("error code not 0--data-->",data);
}
$(document).off('click').on('click', '.treeNode a', function() {
console.log("on click of a-->");
var id = $(this).parent().attr('id');
console.log("id-->",id);
getGroupsStructure(id);
console.log("after getGroupsStructure");
});
});
getGroupsStructureForUserService.error(function(data) {
console.log(" empty error");
// console.log(err);
});
}
The JSP Code is
def NextLevelLDAP(String DN) {
// println "Next Level===>"
assert ldap!=null
def responseArray=[]
def results=ldap.search('objectClass=*',DN,SearchScope.ONE) //Will be triggered when + is pressed in GUI to get next level of tree
// assert results==null
if(DN.startsWith("c="))
{
JSONObject responseJson1=new JSONObject()
responseJson1.put("id", initialDN )
responseJson1.put("parent", "#")
responseJson1.put("text","Parent")
responseArray.add(responseJson1)
for(entry in results) {
// println entry
// println "In NextLevel Using InitialDN"
JSONObject responseJson=new JSONObject()
responseJson.put("id", entry.dn)
responseJson.put("parent", DN)
String tempResDN=entry.dn.toString()
def tempLength=tempResDN.length() - DN.length()
// println tempResDN
String tempName=tempResDN.substring(2,tempLength-1)
// println tempName
responseJson.put("text",tempName)
responseArray.add(responseJson)
// println entry
println responseJson.toString()
}
return responseArray
}
if(results.size!=0)
{
for(entry in results) {
println entry
JSONObject responseJson=new JSONObject()
responseJson.put("id", entry.dn)
responseJson.put("parent", DN)
String tempResDN=entry.dn.toString()
def tempLength=tempResDN.length() - DN.length()
// println tempResDN
String tempName=tempResDN.substring(2,tempLength-1)
println tempName
responseJson.put("text",tempName)
responseArray.add(responseJson)
// println entry
}
return responseArray
}
}
Please Ignore the way of getting the Parent ID. Its Something COmplicated.
Please help me out how do I get The tree nodes created dynamically. I am just getting the fist level of the tree. The data on click for other levels is being shown in the console but not getting attached to the tree.
Thank you.
You have it the other way around - you need to create the tree and have it make the request for you, so instead of this:
'data': function (obj, cb) {
cb.call(this, data.treeData);
}
Use something like this:
'data': function (obj, cb) {
// you probably need to pass the obj.id as a parameter to the service
// keep in mind if obj.id is "#" you need to return the root nodes
service(...).success(function (data) {
cb.call(this, data.treeData);
});
}
This way you do not need to detach and reattach click handlers every time and it will work out of the box for opening nodes. If you want to open a node on click, you can use this:
$('#tree').on('select_node.jstree', function (e, data) {
data.instance.open_node(data.node);
});
So your whole code should look something like this:
function load(id) {
var params = {
"DN" : id && id !== '#' ? id : "c=de"
};
return service(webURL + "sendingValues/getGroupsStructureForUser", params, "POST");
}
$('#tree')
.jstree({
'core' : {
'data': function (obj, cb) {
load(obj.id).success(function (data) {
cb.(data.treeData);
});
}
}
})
.on('select_node.jstree', function (e, data) {
data.instance.open_node(data.node);
});
Just make sure you mark the nodes your return as having children (set their children property to boolean true).

AngularJS + Parse REST API - Paging through more than 1,000 results

Im using Parse REST API + AngularJS and Im trying to be able to get more than 1000 items per query. I try to develop a recursive function and concatenate each query until I get all the data. My problem is that I am not able to concatenate the JSON objects successfully. Here is what I have:
$scope.getAllItems = function(queryLimit, querySkip, query) {
$http({method : 'GET',
url : 'https://api.parse.com/1/classes/myClass',
headers: { 'X-Parse-Application-Id':'XXX','X-Parse-REST-API-Key':'YYY'},
params: {limit:queryLimit, skip:querySkip},
}).success(function(data, status) {
query.concat(data.results);
if(query.lenth == queryLimit) {
querySkip += queryLimit;
queryLimit += 100;
$scope.getAllItems(queryLimit, querySkip, query);
} else {
$scope.clients = query;
}
})
.error(function(data, status) {
alert("Error");
});
};
var myQuery = angular.toJson([]); //Am I creating an empty JSON Obj?
$scope.getAllItems(100,0, myQuery);
Is there any better solution to achieve this?
There may be better, more concise ideas available, but this is what I worked out for myself.
In my service ...
fetch : function(page, perpage) {
var query = // build the query
// the whole answer to your question might be this line:
query.limit(perpage).skip(page*perpage);
return query.find();
},
fetchCount : function() {
var query = // build the same query as above
return query.count();
},
In the controller...
$scope.page = 0; // the page we're on
$scope.perpage = 30; // objects per page
MyService.fetchCount().then(function(count) {
var pagesCount = Math.ceil(count / $scope.perpage);
$scope.pages = [];
// pages is just an array of ints to give the view page number buttons
for (var i=0; i<pagesCount; i++) { $scope.pages.push(i); }
fetch();
});
function fetch() {
return MyService.fetch($scope.page, $scope.perpage)).then(function(results) {
$scope.results = results;
});
}
// functions to do page navigation
$scope.nextPage = function() {
$scope.page += 1;
fetch();
};
$scope.prevPage = function() {
$scope.page -= 1;
fetch();
};
$scope.selectedPage = function(p) {
$scope.page = p;
fetch();
};
Then paging buttons and results in my view (bootstrap.css)...
<ul class="pagination">
<li ng-click="prevPage()" ng-class="(page==0)? 'disabled' : ''"><a>«</a></li>
<li ng-repeat="p in pages" ng-click="selectedPage(p)" ng-class="(page==$index)? 'active' : ''"><a>{{p+1}}</a></li>
<li ng-click="nextPage()" ng-class="(page>=pages.length-1)? 'disabled' : ''"><a>»</a></li>
</ul>
<ul><li ng-repeat="result in results"> ... </li></ul>
I fixed my recursive function and now its working. Here it is:
$scope.getAllItems = function(queryLimit, querySkip, query, first) {
$http({method : 'GET',
url : 'https://api.parse.com/1/classes/myClass',
headers: { 'X-Parse-Application-Id':'XXX','X-Parse-REST-API-Key':'YYY'},
params: {limit:queryLimit, skip:querySkip},
}).success(function(data, status) {
if(first) {
query = data.results;
first = !first;
if(query.length == queryLimit) {
querySkip += queryLimit;
$scope.getAllItems(queryLimit, querySkip, query, first);
} else {
$scope.clients = query;
}
} else {
var newQ = data.results;
for (var i = 0 ; i < newQ.length ; i++) {
query.push(newQ[i]);
}
if(query.length == queryLimit + querySkip) {
querySkip += queryLimit;
$scope.getAllItems(queryLimit, querySkip, query, first);
} else {
$scope.clients = query;
}
}
})
.error(function(data, status) {
alert("Error");
});
};
Simply pushed each element to my empty array, also I was mutating queryLimit instead of querySkip in order to iterate through all the elements.

How can I aggregate when I'm mapping in KnockoutJS?

I'm working with KnockoutJS for a few days now and I have just faced with a simple problem that I cannot solve!
I have a model like this:
function Contact() {
var self = this;
self.name = ko.observable("");
self.phones = ko.observableArray([]);
self.faxes = ko.observableArray([]);
self.address = ko.observable("");
}
I have to call a service which will return repeatitive rows if each contact contains more that one phone or fax. e.g. :
{{"name":"Name1","phone":"1234","fax":"5654","address":"abc"},{{"name":"Name1","phone":"2323","fax":"8787","address":"abc"}}
I do a call like to server like this:
self.GetContacts = function () {
$.getJSON(self.queryUrl(),
function (data) {
if (data.results) {
self.contacts(ko.toJS(data.results));
}
});
There is no way to aggregate it on the serverside as it is an out-of-the-box tool and the only possible way is to aggregate it on the client side.
How can I aggregate them using my custom model, before binding them?
I would do something like that :
function aggragateContacts(data) {
var contacts = [];
ko.utils.arrayForEach(data, function (contactData) {
// looking an existing contact with the same name and address
var contact = ko.utils.arrayFirst(contacts, function (c) {
return c.name() == contactData.name && c.address() == contactData.address;
});
// otherwise create one
if (contact == null) {
contact = new Contact();
contact.name(contactData.name);
contact.address(contactData.address);
contacts.push(contact);
}
contact.phones.push(contactData.phone);
contact.fax.push(contactData.fax);
});
}
self.GetContacts = function () {
$.getJSON(self.queryUrl(),
function (data) {
if (data.results) {
self.contacts(aggragateContacts(ko.toJS(data.results)));
}
})
}

kendo treeview with new data source

Ok, so I have this situation here:
A CSHTML view with a kendo tree in it:
#(Html.Kendo().TreeView()
.Name("treeview")
.DataTextField("Name")
.DataSource(d => d.Read(r => r.Action("WorkedHours", "TaskManager")))
.Events(e => e.Select("onSelect"))
)
to the right of that there is a kendo grid. and above the tree there is a (kendo) dropdown list to select a user.
this is the controller method called by the tree:
public JsonResult WorkedHours(uint? id)
{
DocObjectArray docObjects = null;
if (id == null)
{
// get root elements
var loggedInUserRef = OmanagerUtils.GetInstance().LoggedInUser;
if (loggedInUserRef != null && loggedInUserRef.GetObject() != null && loggedInUserRef.GetObject().SubObjects != null)
{
for (int i = 0; i < loggedInUserRef.GetObject().SubObjects.GetLength(); i++)
{
var item = loggedInUserRef.GetObject().SubObjects.GetAt(i);
if (item.ToString() == TaskManagerConstants.UserWorkHours)
{
docObjects = item.TreeSubObjects;
break;
}
}
}
}
else
{
// get sub objects of a root object
var rootObj = new DocObjectRef((int)id);
docObjects = rootObj.GetObject().TreeSubObjects;
}
var returnDocObjects = new List<OmanagerItem>();
for (int i = 0; i < docObjects.GetLength(); i++)
{
var item = docObjects.GetAt(i);
var hasChildren = true;
if (item.TreeSubObjects == null)
{
hasChildren = false;
}
else
{
if (item.TreeSubObjects.GetLength() == 0)
{
hasChildren = false;
}
}
var listItem = new OmanagerItem
{
hasChildren = hasChildren,
id = item.GetOID(),
Name = item.ToString()
};
returnDocObjects.Add(listItem);
}
return Json(returnDocObjects, JsonRequestBehavior.AllowGet);
}
now, the problem is that i have to be able to select a user from the dropdown list and refresh the tree with this new data.
$("#employee").kendoDropDownList({
change: function () {
var postdata = {
id:$("#employee").val()
}
$.ajax({
url: "TaskManager/WorkedHours",
cache: false,
type: "POST",
data: postdata,
success: function (data) {
$("#treeview").data("kendoTreeView").setDataSource(data);
},
});
}
});
the problem is what do i do with this data? because my attempt did not really work.
many thanks.
You can use OutputCache attribute on WorkedHours action:
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "None")]
public JsonResult WorkedHours(uint? id)
{
// rest of method
}
It helped in my case :)
Maybe this little snippet is of any help to you.
Similar to your code in the change event of my dropdown I'm calling a function that will change the request data of my TreeView DataSource.
After changing it, it calls the read() handler of the datasource so it re-reads the data:
function loadTreeViewData() {
var employee = $('#employee').getKendoDropDownList().dataItem();
WorkedHoursDataSource.transport.options.read.data = {Employee_Id:employee.id};
WorkedHoursDataSource.read();
}