Kendo MVVM Grid - Do I Need to Parse JSON Data? - json

I am having trouble getting JSON data to display in my grid. The html:
<div data-role="grid" data-bind="source: systems" data-columns='["SystemName", "SystemKey"]' ></div>
The mvvm view model:
var viewModel = kendo.observable({
isVisible: true,
systems: new kendo.data.DataSource({
schema: {
model: {
id: "system_id"
}
},
transport: {
read: {
url: "/api/HomeApi?method=Ref/Systems"
}
}
})
});
kendo.bind($("#systems"), viewModel);
The structure of the JSON Data:
- JSON
- Data
- Data
{}
SystemName=TIBCO
SystemKey=TIBCO
..... etc
Now, if the data were to come back in the following format, it would display fine:
[{ "SystemKey": "TIBCO", "SystemName": "TIBCO" }, { "SystemKey": "TIBCO", "SystemName": "TIBCO" }]
And yet, as stated, the actual data is in a more complex structure, rather than the simple structure above. So, do I have to parse this in some way, perhaps using schema.parse, to extract the SystemName and SystemKey, since it is down a few levels? Currently no data is displayed in the grid and I get "Uncaught TypeError: undefined is not a function " as an error.

The answer is yes, I do have to use schema.parse. This is what did it:
schema: {
parse: function (response) {
var systems = [];
for (var i = 0; i < response.Data.Data.length; i++) {
var system = {
SystemName: response.Data.Data[i].SystemName,
SystemKey: response.Data.Data[i].SystemKey
};
systems.push(system);
}
return systems;
}
}

Related

How to get data from a for each loop to graph with Chartjs?

I am using MVC with C#. I am trying to get data from inside the for each loop and try to graph those arrays with Chartjs. I was successful doing it using Json inside the Model folder to pass it but I had to write about 10 functions for the 10 graphs. That is useless to me because I want to create multiple graphs and be able to do it through 1 function. I am not familiar with ajax but I was looking into it and it seems like that's something that would be able to help me.
My Razor file:
...
<canvas id="myChart"></canvas>
...
<script>
var xValues = ["Spain", "Germany", "Argentina"];
var yValues = #Model.ModelData
var barColors = ["red", "green","blue","orange","brown"];
new Chart("myChart", {
type: "bar",
data: {
labels: xValues,
datasets: [{
backgroundColor: barColors,
data: yValues
}]
},
options: {
legend: {display: false},
title: {
display: true,
text: "Graph Title"
}
}
});
</script>
My Model File:
...
public String ModelData{
get{
var Country = CountryData.Where(..).GroupBy(...);
var CountryList = new List<int>();
foreach(var num in Country){
CountryList.Add(num...);
}
return Json.SerializeObject(CountryList);
}
}
I have each of these about 9 other times in order to graph the data that simply varies by the group by condition. So I am just wondering if there is another way to have this foreach loop inside the razor file and obtain the data from there and graph it. I don't have to have the loop inside the Model folder if it's not needed. Not sure if ajax or json is required but please help me out guys.

Loading some XML into JSON in NodeJS

I am new to NodeJS and trying to figure out how to load some xml data from a REST service and convert it to JSON so I can afterwards load it into my view.
I'm trying to do so querying with Hapi API and loading it into an xml parser then convert it to JSON.
Doing the following seems loading correctly the xml object and when printing it it actually shows me some JSON. Does it mean that I don't need to convert to JSON anymore?
const server = new Hapi.Server();
...
server.route({
method: 'GET',
path: '/',
handler: function (request, reply) {
Request.get('http://ws.seloger.com/search.xml?&idtt=2&idtypebien=2,1&ci=750056&pxmax=400000&tri=initial&naturebien=1,2&surfacemin=65search.xml?',
function (error, response, body) {
if (error) {
throw error;
}
var parse = require('xml-parser');
var inspect = require('util').inspect;
var obj = parse(body);
console.log(inspect(obj, { colors: true, depth: 4 }));
Note that the JSON displayed is also not what I am looking for, ie. showing the details with attributes, children, etc.:
{ declaration: { attributes: { version: '1.0', encoding: 'UTF-8' } },
root:
{ name: 'recherche',
attributes: {},
children:
[ { name: 'resume',
attributes: {},
children: [],
content: '....' },
However looking for something more like this (might be just a different representation)
So I figured out that my issue seemed to have been related to the parser itself. Using this one I get what I need:
var parseString = require('xml2js').parseString;
parseString(body, function (err, jsonData) {
reply.view('index', { result: body });
});

Complicated nested json loops to store with extjs

I'm using a geojson extracted from naturalearthdata which looks like that :
All I want is to catch the NAME of each feature in order to display them in a grid (live search grid.. BTW is it efficient for 2000 names?)
But I can't access to all the name with root property. I tried to loop into all the features
Ext.define('myApp.store.Places', {
extend: 'Ext.data.Store',
alias: 'store.places',
requires : ['myApp.model.PlacesModel',
'myApp.view.main.MainModel'],
id: 'Places',
model: 'myApp.model.PlacesModel',
autoLoad: true,
proxy: {
type: 'ajax',
url : '/resources/data/coord.json',
reader: {
type: 'json',
transform: {
fn: function(data) {
for(var i = 0; i < data.features.length -1; i++){
names_places.push(data.features[i].properties.NAME);
}
debugger;
return names_places;
},
scope: this
}
}
}
});
But the debugger sent me that result which I don't understand :
Especially when the array looks good :
What is the good way to catch only the NAME? Does the return has to look to a json?
You can use the mapping attribute on the fields array in your model definition to map the correct attribute in the json to a field.
You set the rootProperty to features for the reader.
Then in your fields array something similar to this
fields: [
{ name: 'myCustomField', mapping: 'properties.NAME' }
]

Reformat API data to Ember friendly array of objects | Ember data with unconventional endpoint

This is a question about molding some API data to fit some needs. I've heard it called "munging." I guess the heart of if is really re-formatting some JSON, but It would be ideal to do it the Ember data way...
I'm getting this data in an Emberjs setting - but it shouldn't really matter - ajax, ic-ajax, fetch, etc... I'm getting some data:
...
model: function() {
var libraryData = ajax({
url: endPoint,
type: 'GET',
dataType: 'jsonp'
});
// or most likely the ember-data way
// this.store.findAll(...
console.log(libraryData);
return libraryData;
}
...
The URL is getting me something like this:
var widgetResults = {
"settings": {
"amazonchoice":null,
"show":{
"showCovers":null,
"showAuthors":null
},
"style":null,
"domain":"www.librarything.com",
"textsnippets":{
"by":"by",
"Tagged":"Tagged","readreview":"read review","stars":"stars"
}
},
"books":{
"116429012":{
"book_id":"116429012",
"title":"The Book of Three (The Chronicles of Prydain Book 1)",
"author_lf":"Alexander, Lloyd",
"author_fl":"Lloyd Alexander",
// ...
The promise that is actually returned is slightly different.
My goal is to get to those books and iterate over them - but in my case it wants an array. that #each loops over must be an Array. You passed {settings: [object Object], books: [object Object]} - which makes sense.
In and ideal API the endpoint would be / http:/site.com/api/v2/books
and retrieve the data in this format:
{
"book_id":"116428944",
"title":"The Phantom Tollbooth",
"author_lf":"Juster, Norton",
"author_fl":"Norton Juster",
...
},
{
"book_id":"116428944",
"title":"The Phantom Tollbooth",
"author_lf":"Juster, Norton",
"author_fl":"Norton Juster",
...
},
{
... etc.
I would expect to just drill down with dot notation, or to use some findAll() but I'm just shooting in the dark. Librarything in specific is almost done with their new API - but suggest that I should be able to loop through this data and reformat it in an ember friendly way. I have just looped through and returned an array in this codepen - but haven't had luck porting it... something about the returned promise is mysterious to me.
How should I go about this? am I pointed in the wrong direction?
I've tried using the RESTAdapter - but didn't have much luck dealing with more unconventional endpoints.
Custom Adapters / Serializers ?
this article just appeared: "Fit any backend into ember with custom adapters and serializers
Full url with endpoint in question
model (just title to test)
import DS from 'ember-data';
export default DS.Model.extend({
title: DS.attr('string')
});
route ( per #Artych )
export default Ember.Route.extend({
model() {
$.ajax({
url: endPoint,
type: 'GET',
dataType: 'jsonp'
}).then((widgetResults) => {
// modify payload to RESTAdapter
var booksObj = widgetResults.books;
var booksArray = Object.keys(booksObj).map((element) => {
var book = booksObj[element];
book.id = book.book_id;
delete book.book_id;
return book;
});
console.log(booksArray);
this.store.pushPayload({books: booksArray});
});
return this.store.peekAll('book');
}
});
template
{{#each model as |book|}}
<article>
<h1>{{book.title}}</h1>
</article>
{{/each}}
There is straightforward solution to process your payload in model():
Define book model.
Process your payload in model() hook:
model() {
$.ajax({
url: endPoint,
type: 'GET',
dataType: 'jsonp'
}).then((widgetResults) => {
// modify payload to RESTAdapter
var booksObj = widgetResults.books;
var booksArray = Object.keys(booksObj).map((element) => {
var book = booksObj[element];
book.id = book.book_id;
delete book.book_id;
return book;
});
this.store.pushPayload({books: booksArray});
});
return this.store.peekAll('book');
}
Iterate model in controller or template as usual.
Working jsbin:
ember 1.13
ember 2.0
You want a custom serializer to translate the data from that format into JSON-API. JSON-API is an extremely well thought-out structure, so well in fact that ember-data has adopted it as the default format used internally. Some of the benefits are that it defines a structure for objects themselves, separating attributes from relationships; a means for embedding or including associated resources; defines a place for errors and other metadata.
In short, for whatever you're trying to do, JSON-API probably has already done a lot of the decision-making for you. And, by subclassing from DS.JSONSerializer, you'll be mapping right into the format that ember-data needs.
To do this, you create a custom adapter using ember generate serializer books:
// app/serializers/book.js
import DS from 'ember-data';
export default DS.JSONSerializer.extend({
normalizeResponse(store, primaryModelClass, payload, id, requestType) {
// payload will contain your example object
// You should return a JSON-API document
const doc = {};
// ...
return doc;
}
});
For your example data, the output of the normalization should look something like this:
{
"data": [
{
"type": "books",
"id": 116429012,
"attributes": {
"title": "The Book of Three (The Chronicles of Prydain Book 1)",
"author_lf": "Alexander, Lloyd",
"author_fl": "Lloyd Alexander"
}
},
{
"type": "books",
"id": 1234,
"attributes": {
}
}
],
"meta": {
"settings": {
"amazonchoice":null,
"show":{
"showCovers":null,
"showAuthors":null
},
"style":null,
"domain":"www.librarything.com",
"textsnippets":{
"by":"by",
"Tagged":"Tagged","readreview":"read review","stars":"stars"
}
}
}
};
Then do
this.get('store').findAll('books').then((books) => {
const meta = books.get('meta');
console.log(meta.settings.domain);
books.forEach((book) => {
console.log(book.get('title'));
});
});
Code is not tested, but hopefully it gets you started.
Define settings and book models. Arrange for the API to respond to the endpoint /books returning data in the format:
{
settings: { ... },
books: [
{
id: xxx,
...
}
]
}
Retrieve the data in the model hook with this.store.findAll('book').
Iterate over the books in your template with {{#each model as |book|}}.

How to make a store with jsonreader using metadata in Extjs 4?

Is it possible to create a store that will read json, and use fields specified in the metadata in the json as a model?
I want to say something like:
var store = new Ext.data.Store({
autoLoad: {
params: {
metaNeeded: true
}
},
reader: new Ext.data.JsonReader({fields:[]}),
proxy: new Ext.data.HttpProxy({
api: {
url: 'php/chart-data.php'
}
})
});
I've tried a number of combinations however I cannot seem to get it to work.
I currently get the error "Cannot call method 'indexOf' of undefined". I've had others including "object has no read method".
The json I am sending is:
{
metadata:{
root:"rows",
sortInfo:{
field:"date",
direction:"ASC"
},
fields:[ {
name:"date"
}, {
name:"flow"
},{
name:"limit"
}
],
idProperty:"date"
},
success:true,
rows: << snip >>
}
Is it possible to have the store's model configured by the data that it receives, so I could use the same store later with different fields (e.g. date, flow, limit and temperature)?
I have gotten it to work with the following:
var store = new Ext.data.Store({
proxy: {
type: 'ajax',
url: 'php/chart-data2.php',
reader: new Ext.data.JsonReader({
fields:[]
})
}
});
And the php that sends the json:
'{"metaData":{
"root":"rows",
"fields": [
{"name":"date",
"type":"number",
"convert": function(val, rec) {
return val*1000
} },
{"name":"flow"},
{"name":"limit"}
]
},
"totalCount":'.count($chart).',
"success":true,
"rows":' . json_encode($chart) . '
}'
This now allows the server to specify the data (that's getting displayed in a chart), and can add in series dynamically. I don't know if it is good, but it works. I am kind of disappointed in the lack of documentation about this.