WinJS Need help binding json response to listview - json

I have been messing with the code trying to get json to bind with winJS listview.
At the moment I an getting an error Exception: Cannot use 'in' operator to search for '0' in [{"$id":"1","Distance":0.083516275210499508,"Jo............
Need some help, thanks
WinJS.xhr({
url: "http://api.secondyearvisajob.com.au/api/jobs/GetNearActiveJobs",
type: "POST",
responseType: "",
data: JSON.stringify({ LocationId: 23555, kms: 10 }),
headers: { "content-type": "application/json" }
}).done(
function completed(request) {
alert(request) //[object: Object]
alert(JSON.stringify(request.response)) // my data
alert(JSON.parse(request.response)) //[object: Object],[object: Object]
alert(request.statusText)
WinJS.Namespace.define("Sample.ListView", { data: new WinJS.Binding.List(request.response) });
},
function error(request) {
alert(request)
}
);
WinJS.UI.processAll()
<div class="smallListIconTextTemplate" data-win-control="WinJS.Binding.Template" style="display: none">
<div class="smallListIconTextItem">
<div class="smallListIconTextItem-Detail">
<h4 data-win-bind="textContent: Distance"></h4>
</div>
</div>
</div>
<div id="listView"
class="win-selectionstylefilled"
data-win-control="WinJS.UI.ListView"
data-win-options="{
itemDataSource: itemDataSource :Sample.ListView.data.dataSource,
itemTemplate: select('.smallListIconTextTemplate'),
selectionMode: 'none',
tapBehavior: 'none',
layout: { type: WinJS.UI.ListLayout }
}">
</div>

There are a couple things happening here in your code.
First of all, request.response from your REST call is a JSON string, not an array as is required to initialize a new WinJS.Binding.List. The exception you're seeing is coming from passing a string. So you need to use JSON.parse(request.response) to get that array:
var arr = JSON.parse(request.response);
var list = new WinJS.Binding.List(arr);
Next, because WinJS.xhr is an asynchronous API, what's probably true is that WinJS.UI.processAll is attempting to initialize the ListView before you have the response and before you've even defined the Sample.ListView namespace. To correct this, omit the itemDataSource property from the HTML, and set that property directly in code. That is, continuing from the above:
var listview = document.getElementById("listView");
listview.winControl.itemDataSource = list.dataSource;
And the data-win-options attribute in HTML looks like this:
data-win-options="{
itemTemplate: select('.smallListIconTextTemplate'),
selectionMode: 'none',
tapBehavior: 'none',
layout: { type: WinJS.UI.ListLayout }
}"
That should help you move forward.
P.S. Just a suggestion, when posting questions about exceptions it's always helpful to identify exactly where in the code the exception is raised. That'll get you faster and better responses, as otherwise I had to put your code into a project to find that information.

Related

Unexpected end of JSON input... SO Wants more info

I'm confused... What's wrong with this?
Couldn't post without changing the title... I seriously don't know what's wrong
$(document).ready(function(){
$("#fmob").click(function(){
var mobname = $(this).attr("data-value");
console.log(mobname);
$.ajax({
type: "POST",
url: "/system/mobproc.php",
data: {mobname: 1},
dataType: "json",
success: function(data){
if(data.response === true){
$("#fresponse").html(data.result);
}else{
$("#fresponse").html(data.result);
}
},
error:function(jqXHR,textStatus,errorThrown ){
alert('Exception:'+errorThrown );
}
});
});
});
I looked up here Unexpected end of JSON input from an ajax call
but somehow not what I expected... What's wrong? Thanks.
Try this approach:
$(document).ready(function(){
$("#fmob").click(function(){
var mobname = $(this).attr("data-value");
console.log(mobname);
var data = {}; // setup a data object
data[mobname] = 1; // add the property with the key of the value of the "mobname" variable, with the data of 1 (per question)
$.ajax({
type: "POST",
url: "/system/mobproc.php",
data: data, // pass the data object as the POST data instead of defining an object inline
dataType: "json",
success: function(data){
if(data.response === true){
$("#fresponse").html(data.result);
}else{
$("#fresponse").html(data.result);
}
},
error:function(jqXHR,textStatus,errorThrown ){
alert('Exception:'+errorThrown );
}
});
});
});
Note the lines with comments, above.
In this approach, we setup a data object and specify a property using the value of the "mobname" variable, instead of defining the property inline. This allows us to use the dynamic value of the variable as the key for the property.
I guess the problem is with the line: data: {mobname: 1}
As you can't assign a variable name as object property like that... it should be inside a square brackets like this data: {[mobname]: 1}
EDIT: if you aren't using browser supported by ES 2015 you could even do
data: JSON.parse('{"'+mobname+'":1}')
EDIT 1 if you want to send the json data as string and convert that on php side you could simply do data: '{"'+mobname+'":1}'
This might cause your ajax call to fail, and might not return a JSON as you're expecting (using the line dattype:JSON);
So removing datatype:JSON can also help you by showing what you're doing wrong
JSON objects are differentiated from standard JavaScript objects by using double quoted in both the key and the value - unless either is an integer.
It is explained in the relevant W3Schools site.
Therefore, in your AJAX request, you have to send a properly formatted JSON object:
$.ajax({
type: "POST",
url: "/system/mobproc.php",
data: {"mobname": 1}, //here's the change
dataType: "json",
/* rest of the code */
You can of course pass a variable as well:
var JSON_obj = {"mobname": 1, "othermob": 2, /*rest of the JSON */ };
$.ajax({
type: "POST",
url: "/system/mobproc.php",
data: JSON_obj, //here's the change
dataType: "json",
/* rest of the code */
Again, with properly formatted JSON objects (and with properly included JS script if it's in another file), this should work.

Backbone model .toJSON() doesn't work after .fetch()

Good day! I need to render a model's attributes to JSON so I can pass them into a template.
Model:
var UserInfo = Backbone.Model.extend({
url: appConfig.baseURL + "users/",
});
Template:
<script type="text/html" class="template" id="profile-form">
<h2 class="ui-li-heading"><%= username %></h2>
<p class="ui-li-desc"><strong><%= phone %></strong></p>
</script>
View:
var ProfilePageView = Backbone.View.extend({
events: {
'click #edit': "edit"
},
initialize: function () {
this.template = $.tpl['profile-form'];
var user = new UserInfo()
user.fetch({
data: $.param({email: localStorage.getItem('user_email')}),
type: 'POST'
});
console.log(user) //returns correct object with attrs
console.log(user.toJSON()) //returns empty object
},
render: function (eventName) {
$(this.el).html(this.template());
},
edit: function () {
window.workspace.navigate('#account/edit', { trigger: true});
}
});
When i put in console something like this, user.toJSON() returns correct data
var user = new UserInfo();
user.fetch({
data: $.param({email: localStorage.getItem('user_email')}),
type: 'POST'
});
But when i put it to my view, its returns Object {}.
Where is a mistake or tell me how can differently pass to the template data received from the server in json format? Thanks!
You appear to have two problems. fetch is asyncronous, so you need to use a callback to use the information. But first, an explanation about toJSON. .toJSON() doesn't actually return a JSON string, it returns an object that is what you want JSON to stringify. This allows you to modify the toJSON method to customize what attributes will be taken from your model or collection and added to the JSON string representation of your model. Here is a quotation from the Backbone.js docs:
toJSON collection.toJSON([options])
Return a shallow copy of the model's attributes for JSON
stringification. This can be used for persistence, serialization, or
for augmentation before being sent to the server. The name of this
method is a bit confusing, as it doesn't actually return a JSON string
— but I'm afraid that it's the way that the JavaScript API for
JSON.stringify works.
So you should replace this line in your code
console.log(user.toJSON())
with this one
console.log(JSON.stringify(user))
The object that you saw was returned by toJSON will then be turned into JSON.
Now, even after you do that, it won't work properly, because you will execute the console.log before you get the data for your model from fetch. fetch is asynchronous, so you need to call any code you want to be executed after the fetch is done in the success callback:
user.fetch({
data: $.param({email: localStorage.getItem('user_email')}),
type: 'POST',
success: function(){
console.log(user);
console.log(JSON.stringify(user));
}
});

Extjs is passing my cfc a json string that I can not read

I am playing with the ExtJs4 cartracker application written by existdisolve. I was able to change his queries from rest requests to ajax requests. I also modified the api calls to use ajax to make ajax requests for updates.
I am not getting form or url data passed to my cfc. Instead, in firebug I see JSON passed. I am confused if it is not passed in the form or the url, how is this passed and how do I get to the data? I have tried deserialized the form and url and dumping these after the deserialize and I am told that it is not json.
Where would I find the json?
I am not allowed to post a picture. But it looks like this in the xhr window:
JSON
Active true
ColorID null
Shortname red
Longname Blood Red
So if it is being passed why can I not get to it?
Edit:
#existdissolve - I replaced the rest.js with ajax.js which looks like this:
/**
* Abstract REST proxy
*/
Ext.define('CarTracker6.proxy.Ajax', {
extend: 'Ext.data.proxy.Ajax',
alias: 'proxy.baseajax',
/*format: 'json',*/
limitParam: 'max',
startParam: 'offset',
sortParam: 'sortorder',
writer : {
type : 'ajax',
encode : false,
writeAllFields : true,
root : 'data',
allowSingle : true,
batch : false,
method: 'post',
params: { record: 'record' },
writeRecords : function(request, data) {
request.jsonData = data;
return request;
}
},
reader: {
type: 'json',
root: 'data',
totalProperty: 'count'
},
api: {
read: 'api/option/colors.cfc?method=getcolors',
create: 'api/option/colors.cfc?method=addcolors',
update: 'api/option/colors.cfc?method=updatecolors',
destroy: 'api/option/colors.cfc?method=deletecolors'
}
});
My read works perfectly and I can call the correct cfcs for colors, statuses, etc. and retrieve the requisite data. I am looking to pass parameters to the CFCs and that is not working.
see http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.data.writer.Json-cfg-encode:
if the encode property of your writer is set to false, all data is sent as raw post body. Instead, you can use
encode: true,
root: 'data', // must be set if encode is true

knockout's viewModel does not get updated

I have the following knockout's viewModel :
var viewModel={
businessName: "",
....
}
I also tried to identify the field like this: businessName: ko.observable("")
Then, I have a load method that requests for a JSon with a newly populated data
And this is how I'm trying to apply the new data:
$.ajax({
//
url: "#Html.Raw(#Url.Action("Load"))",
type: "post",
data: ko.toJSON(this),
contentType: "application/json",
success: function (result) {
//OPTION 1:
viewModel.businessName = result.vm.BusinessName;
//OPTION 2:
var viewModel2 = ko.mapping.fromJS(result.vm);
console.log(viewModel2.businessName);
}
});//ajax
As a result:
if I use Option1, I get the new data but it does not get updated on the page.
If I use Option2, it writes "undefined"
Please advise how can I update the new data on the page?
I checked the similar topics but there is no answer that helps
PS
It seems I resolved OPTION 1. But still don't understand why OPTION 2 does not work
ko.observable is a function, not a property. So you get it's value like this:
var whatsTheValue = myVM.MyObservable();
and you set it like this:
myVM.MyObservable(newValue);
This is all in the docs.
Note, however, when using the data-bind syntax in your HTML, you don't need to explicitly unwrap your observable by using the parenthesis because KO is smart enough to do it automatically:
<span data-bind="text: MyObservable"></span>
You have to use ko.observable in the ViewModel and access/write it accordingly.
var myViewModel = {
businessName = ko.observable('')
};
...
$.ajax({
...
success: function(result) {
myViewModel.businessName(result.vm.BusinessName);
},
...
});
Otherwise your view won't have any clue you changed businessName. In the implementation ko.observable, besides actually storing the new value, broadcasts some events to your view, letting it know the stored value changed.

Why is my dijit.Tree not populated from json source?

I am new to dojo and spring development. I am trying to populate a Tree widget using a json response from a spring-mvc controller. I'm following the examples from the dojocampus website quite closely.
Firstly if I use a local data source it works ok:
<script type="text/javascript">
dojo.require("dojo.data.ItemFileReadStore");
dojo.require("dijit.Tree");
dojo.addOnLoad(function() {
var rawdata = [{"rid":"b1c","name":"Test Parent","children":[{"rid":"1c4","name":"Test Child 1","children":[]},{"rid":"ee6","name":"Test Child 2","children":[]}]}];
var store = new dojo.data.ItemFileReadStore({
data: {
identifier: 'rid',
label: 'name',
items: rawdata
}
});
var treeModel = new dijit.tree.TreeStoreModel({
store: store,
query: {name: 'Test Parent'},
childrenAttrs: ["children"]
});
new dijit.Tree({
model: treeModel
},
"treeOne");
});
</script>
<div id="treeOne">
</div>
But if I use my json url the tree doesn't appear:
<script type="text/javascript">
dojo.require("dojo.data.ItemFileReadStore");
dojo.require("dijit.Tree");
dojo.addOnLoad(function() {
var store = new dojo.data.ItemFileReadStore({
url: "/Demo2/glossaryobjects/categories.json"
});
var treeModel = new dijit.tree.TreeStoreModel({
store: store,
query: {name: 'Test Parent'},
childrenAttrs: ["children"]
});
new dijit.Tree({
model: treeModel
},
"treeOne");
});
</script>
<div id="treeOne">
</div>
When I debug with Firebug I can see that the json response appears to be loaded correctly. It looks like this:
{"identifier":"rid","items":{"rid":"b1c","name":"Test Parent",
"children":[{"rid":"1c4","name":"Test Child 1","children":[]},
{"rid":"ee6","name":"Test Child 2","children":[]}]}, "label":"name"}
There is an error in Firebug:
"dijit.tree.TreeStoreModel: query {"name":"Test Parent"} returned 0 items, but must return exactly one item"
It looks like the ItemFileReadStore is not correctly loaded. Anyone know what I'm doing wrong? I've been tearing my hair out for days trying to get this to work, so any help is much appreciated.
Cheers,
Rod.
OK! Problem solved (for me):
If you have a close look at the store produced by each, the data is there for both, but the way the store represents each is different.
With the url JSON data, you get
_arrayofallitems []
_arrayoftoplevelitems Object {....
id...
items...
etc.
with the string data, you get
_arrayofallitems [] 62 items
_arrayoftoplevelitems
[0]
id
items
etc.
If you intercept the JSON response from xhrGet, and compare it to the string, you'll see that the JSON response is not an array (no []) whereas the string is.
Solution: declare an empty array, push the JSON response into it,
then pass the array to ItemFileReadStore:
dojo.xhrGet( {
url: 'test.php',
handleAs: "json",
preventCache: 'true',
load: function(response, ioArgs){
var rawdata = [];
rawdata.push(response);
var store = new dojo.data.ItemFileReadStore({ data: {
identifier: "id",
label: "label",
items: rawdata }
});
loadtree(store);
}});
It worked for me (finished an afternoon of frustration)...
The error you mentioned:
"dijit.tree.TreeStoreModel: query {"name":"Test Parent"} returned 0 items, but must return exactly one item"
Should be from using a TreeStoreModel instead of a ForestStoreModel. The former requires only one item be returned for the root node. Your fix probably worked because you shoved it into a single array.
Take a look at:
http://ofps.oreilly.com/titles/9780596516482/application_widgets.html