I asked this question earlier this morning
"here is my JSON file :
[
{
"Week": "1145",
"Sev_Logged": "3_major",
"From": "IN1"
},
{
"Week": "1145",
"Sev_Logged": "4_minor",
"From": "IN1"
},
{
"Week": "1145",
"Sev_Logged": "4_minor",
"From": "IN1"
},
{
"Week": "1145",
"Sev_Logged": "4_minor",
"From": "IN1"
},
{
"Week": "1145",
"Sev_Logged": "4_minor",
"From": "IN1"
},
{
"Week": "1145",
"Sev_Logged": "4_minor",
"From": "IN2"
},
{
"Week": "1145",
"Sev_Logged": "3_major",
"From": "IN2"
},
];
I want to count the "from : IN1" field for each "week", per example for week : 1145 i'd get : 3, and for "From : IN2" i'd get 2
Thanks"
Thank you VDP for your answer, so I did this :
My store is now like :
Ext.define('Metrics.store.GraphData', {
extend : 'Ext.data.Store',
model : 'Metrics.model.GraphData',
autoload : true,
proxy : {
type : 'ajax',
url : 'data/metrics_data.json',
reader : {
type : 'json',
root : 'data',
successProperty : 'success'
}
},
//data : GraphData, //povide inline data or load using proxy
countBy: function(param){
var count = {};
this.each(function(item){
var type = item.get(param);
if (Ext.isDefined(count[type])){
count[type]++;
} else {
count[type] = 1;
}
});
return count;
}
});
And my model :
Ext.define('Metrics.model.GraphData', {
extend: 'Ext.data.Model',
//fields: ['week', 'sev']
fields : [
{name: 'Week', type: 'int'},
{name: 'Sev_Logged', type: 'string'},
{name: 'From', type: 'string'}
]
});
Since i'm using extjs 4 with MVC model, I have made a controller wich controls the event of a button, right now it looks like this :
launchGraph : function(button){
console.log('clicked the apply button');
var chartStore = this.getGraphDataStore();
chartStore.load({
callback: this.onGraphDataLoad,
scope: this,
console.log(chartStore.countBy("From"))
});
But when I click the apply button I get this error in my controller :
"Uncaught SyntaxError: Unexpected token . "
And it points to the line :
"console.log(chartStore.countBy("From"))"
It seems like i have an error in the referencing to my store. Any ideas?
If var jsonData is the array resulting from parsing the json shown above, this will give you an object with the counts of each depending on the parameter you use..
function CountBy(parameter) {
var count = {};
for (var i = 0; i < jsonData.length; i++) {
var type = jsonData[i][parameter];
if (count[type] === undefined) {
count[type] = 1;
} else {
count[type]++;
}
}
return count;
}
Result:
CountBy("From") => {"IN1" : 5, "IN2" : 2}
CountBy("Week") => {"1145" : 7}
CountBy("Sev_Logged") => {"3_major": 2, "4_minor": 5}
If you are using the array you provide you can just use the mimikomi's answer or a similar ExtJS version of it:
here is a fiddle
function countBy(data, param) {
var count = {};
Ext.each(data, function(item){
var type = item[param];
if (Ext.isDefined(count[type])) {
count[type]++;
} else {
count[type] = 1;
}
});
return count;
}
If you load that json from an external location it's best practice to load it in a store. You define a model, a store and add 'special' functions to your store for example.
Ext.define('Week', {
extend: 'Ext.data.Model',
fields: [
{name: 'Week', type: 'int'},
{name: 'Sev_Logged', type: 'string'},
{name: 'From', type: 'string'}
]
});
var store = Ext.create('Ext.data.Store', {
model: 'Week',
data : data, //povide inline data or load using proxy
countBy: function(param){
var count = {};
this.each(function(item){
var type = item.get(param);
if (Ext.isDefined(count[type])){
count[type]++;
} else {
count[type] = 1;
}
});
return count;
}
});
var countObject = store.countBy("From");
alert(Ext.encode(countObject));
//chrome developper tools, safari, opera can show us the contents of objects in a log too. IE, FF however only tell us it is an object. (pretty useless)
console.log(countObject);
//you can chose you're favorite notation to retreve the value (but I hope you knew this, it's pretty basic javascript)
console.log(countObject.IN1);
console.log(countObject['IN2']);
Here is a fiddle.
More info on loading json dynamically into a store via ajax (using a proxy)
Related
I am using d3.js's "d3.json(); function to reach out and fetch some data from a REST API.
The data comes back as this:
{
"offset" : 0,
"rows": [
{ "_id":
{ "$oid" : "1234567" },
"mockupData" : [ {
"Analysis" : "Test",
"Description" : "The Test indicates...",
"Data" : [
{ "Category" : "A",
"Statistic" : 0.15,
"Value" : 0.95 },
{ "Category" : "B",
"Statistic" : 0.65,
"Value" : 0.85 },
] } ] }
],
"total_rows" : 1 ,
"query" : {} ,
"millis" : 0
}
I am having an extremely difficult time drilling down in to the json to get what I want.
I'm attempting to set it up like this:
function generateChart(){
var chart;
var Category = [{key:"Stuff", values:[]}];
d3.json('http://url_that_returns_json/', function(error,data{
for(var key in data._SOMETHING_){
switch(key){
case "A":
Category[0] ["values"].push({"label":"Statistic","value""data.Category[key]});
... // same for B
})
// more graph logic
I appear to be missing some entire fragment of knowledge on this. Guidance? Help?
Thanks in advance.
Here is a fiddle I have implemented : https://jsfiddle.net/thatOneGuy/486mwb86/1/
First off, I set the data as a variable so I can use it later. So :
var data = {
"offset": 0,
"rows": [{
"_id": {
"$oid": "1234567"
}, ... //and so on
This is exactly the same as you using :
d3.json('http://url_that_returns_json/', function(error,data{
Both data variables are the same.
Then I got to the point you wanted to check, i.e the categories in the data attribute, like so :
var thisDataSet = data.rows[0].mockupData[0].Data;
As this is an array and not an object, I used a for loop to loop through :
for (var i = 0; i < thisDataSet.length; i++) {
And, in my opinion, you didn't need a switch statement as it looks like you just wanted to populate Category.values with the different categories. So I just pushed the current value of the category in the dataset to this Category.values :
Category[0]["values"].push({
"label": "Statistic",
"value": thisDataSet[i].Category //push category here
});
And that's it. Check the console log for output. Should work fine. Full function :
function generateChart() {
var chart;
var Category = [{
key: "Stuff",
values: []
}];
console.log(data.rows[0].mockupData[0].Data)
var thisDataSet = data.rows[0].mockupData[0].Data;
for (var i = 0; i < thisDataSet.length; i++) {
//for (var key in data.rows[0].mockupData[0].Data) {
console.log(thisDataSet[i])
Category[0]["values"].push({
"label": "Statistic",
"value": thisDataSet[i].Category
});
}
console.log(Category)
}
I have JSON response as below -
{
"success": true,
"data": {
"data": [
{
"resultsMap": {
"Title": "Test1",
"Name": "Test1"
},
"id": 1
},
{
"resultsMap": {
"Title": "Test2",
"Name": "Test2"
},
"id": 2
}
],
"total": 2
}
}
I am using a custom reader to extract the data. Problem is I loose the initial JSON response from the server from which I need to extract the "total". Can someone help me in getting the "total" from the json response?
var newStore = Ext.create('Ext.data.BufferedStore', {
pageSize: 2000,
fields:fields,
//leadingBufferZone:50,
//trailingBufferZone:50,
//autoLoad: {start: 0, limit: 2000},
remoteSort: true,
sorters: [{
property : 'name',
direction: 'asc'
}],
proxy: {
type: 'ajax',
url: 'getData.json',
reader: {
type: 'nestedjsonreader',
rootProperty: 'data',
totalProperty: function(data) {
//console.log(data);
return data.totalCount;
},
},
extraParams: {
id:ID
}
},
listeners: {
'load' : function(store, records, success, options){
//the complete response
console.log(store.getProxy().getReader().rawData);
}
}
});
Ext.define('Portal.model.NestedJsonReader', {
extend: 'Ext.data.reader.Json',
alias: 'reader.nestedjsonreader',
readRecords: function(data) {
var arr = data.data.data;
var data = [];
if(arr!=undefined){
for(var i=0;i<arr.length;i++){
var obj = arr[i].resultsMap;
data.push(obj);
}
}
return this.callParent( [ data ]);
}
})
Create a custom property in your store as resp_total and assign data.total to it.
Basically I want to validate my observable before apply the bindings, so that I will never get that something something is not defined error.
Say I do have a javascript class that defines all that I need, and I want to validate an observable created from ajax against it.
Is there a generic way to do it?
Edit:
http://jsfiddle.net/rgneko/GuR8v/
Currently the demo will throw error because one of the items has no id property. I want to verify whether all items are valid.
$(document).ready(function () {
function ModelToTestAgainst(id, name, type, items) {
this.id = id;
this.name = name;
this.type = type;
this.items = items;
}
var data = {
items: [{
id: 1,
name: 'name1',
type: 'folder',
items: []
}, {
id: 2,
name: 'name2',
type: 'file',
items: []
}, {
name: 'name2',
type: 'file',
items: []
}]
};
var someRandomObservaleIGotFromWherever = ko.mapping.fromJS(data);
// I want to Validate(someRandomObservaleIGotFromWherever) before apply bindings
ko.applyBindings(someRandomObservaleIGotFromWherever);
});
There is a standard JSON Schema, defined in http://json-schema.org/.
An schema can be as simple as:
var schema = {"type" : "object"};
which requires the value to be an object. Or much more complex, like this example from json-schema.org:
{
"title": "Example Schema",
"type": "object",
"properties": {
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
},
"age": {
"description": "Age in years",
"type": "integer",
"minimum": 0
}
},
"required": ["firstName", "lastName"]
}
which requires several properties to exists, defines their types, and even a minimun value for one of them.
Then you need a library that allows to validate the JS objects with this kind of schema. In the same site, you can find a list of libraries for validating (and parsing, creating documentation...). Note that not all libraries are updated, and not all of them support the latest JSON schema version.
For example, using JSV, you can make a validation simply like this:
var report = env.validate(json, schema);
Why don't you map/wrap it into a view model that you know has all the properties that you need?
function ViewModel(model) {
this.x = ko.observable(model.x || 0);
this.y = ko.observable(model.y || 0);
}
var original = { x: 27 }; // Use your ajax object here.
var viewModel = new ViewModel(original);
What about using JSON Schema validation.
I have used library from Tiny Validator to enable validation. Validation is easy to add as an observable extension
$(document).ready(function () {
// Attach a validationSchema method to all observable types
ko.subscribable.fn["validateSchema"] = function(schema){
// Convert the observable back to an object literal to test.
var source = ko.mapping.toJS(this());
return tv4.validate(source, schema);
};
// Define schema for ModelToTestAgainst
var modelSchema = {
"$schema": "http://tempuri.org/ModelToTestAgainst",
"title": "ModelToTestAgainst Set",
"type": "array",
"items": {
"title": "ModelToTestAgainst",
"type": "object",
"properties" : {
"id" : {
"type": "number",
"minimum" : 1
},
"name" : { "type": "string" },
"type" : { "type": "string" },
"items" : { "type" : "array" }
},
"required": ["id", "name", "type", "items"]
}
};
function ModelToTestAgainst(id, name, type, items) {
this.id = id;
this.name = name;
this.type = type;
this.items = items;
}
var data = {
items: [{
id: 1,
name: 'name1',
type: 'folder',
items: []
}, {
id: 2,
name: 'name2',
type: 'file',
items: []
}, {
name: 'name2',
type: 'file',
items: []
}]
};
var obs = ko.mapping.fromJS(data));
var isValid = obs.items.validateSchema(modelSchema);
if( isValid ) {
ko.applyBindings(obs);
}
});
I am working on a user script for a Wikia community ( http://c.wikia.com ) and I need to get array of users (and possibly revision IDs) of a page. I have come up with the following code but cannot seem to make it work. Any help would be appreciated.
Code:
var revisions = [];
$.getJSON('/api.php', {
action: 'query',
prop: 'revisions',
titles: mw.config.get("wgPageName"),
rvprop: 'user',
rvlimit: '50',
format: 'json'
}, function (result) {
for (var i = 0; i < 50; i++) {
var revision = result.query.pages.page[i].revisions.user;
revisions.push(revision);
}
alert(revisions);
});
The query result looks something like this:
{
"query": {
"pages": {
"421588": {
"pageid": 421588,
"ns": 0,
"title": "Community Central",
"revisions": [
{
"user": "Mhadick"
},
{
"user": "Nblonkenfeld"
},
…
]
}
}
},
…
}
You'll notice that pages is an object with property named after the page id of the current page "421588" (judging from your code, you might be looking at the XML version of the response, you have to look at the JSON). To work with that, you can use something like:
var users = [];
$.getJSON('/api.php', {
action: 'query',
prop: 'revisions',
titles: mw.config.get("wgPageName"),
rvprop: 'user',
rvlimit: '50',
format: 'json'
}, function (result) {
var revisions = result.query.pages[mw.config.get("wgArticleId")].revisions;
$.each(revisions, function(key, revision) {
users.push(revision.user);
});
alert(users);
});
Consider this JSON
{
"stream": {
"posts": [{
"post_id": "1",
"post_type": "text",
"post_thumb": "bla1",
"comments": [{
"comment_id": "7",
"comment_text": "asd",
},
{
"comment_id": "8",
"comment_text": "sdf",
}],
}],
}
}
and my Model
Ext.define('MyAppApp.model.Post', {
extend: 'Ext.data.Model',
config: {
fields: [
'post_id',
'post_type',
'post_thumb',
'comments',
],
proxy: {
type: 'jsonp',
url: 'http://MyApp.com/home/index_app',
reader: {
type: 'json',
rootProperty: 'stream'
}
}
}
});
The above correctly shows a list of posts in my view.
I added a controller to push a panel to show the full content of each post, which is working.
Controller
Ext.define('MyAppApp.controller.Main', {
extend: 'Ext.app.Controller',
config: {
refs: {
stream: 'homepanel'
},
control: {
'homepanel list': {
itemtap: 'showPost'
}
}
},
showPost: function(list, index, element, record) {
/////// begin code block that solved my problem
var data = record.get('comments');
var comments = '';
Ext.Array.each(data, function(item) {
comments += [item.comment_text] + '<br />';
});
/////// end
this.getStream().push({
xtype: 'panel',
html: [
'<p>' + record.get('post_thumb') + '</p>',
'<p>' + record.get('comments') + '</p>',
comments // added to output HTML
].join(''),
scrollable: true,
styleHtmlContent: true,
});
}
});
My trouble is with retrieving the data from comments, which are nested in the JSON.
With the above controller, I get
[object Object],[object Object]
in my view and in the console I can open those objects and see the entirety of my comments.
But how do I display them in the view? (eg, how do I display "comment_text"?)
Well, they are no longer JSON as soon as they are in your model, they got deserialized to object. To display them you should use a XTemplate. If you already use a template within your view you can directly access the properties of the objects to to render them. Let me know if anything is still unclear.
Why exactly do you render the content by yourself into html property? Is that cause of performance reasons? I am not that used to ST, therefore I ask. Anyway, build up a little helper function that will loop through the comment array and return is as more or less formatted string (this will be up to you, also the check that the array is at least a empty one and never null)
var data = record.get('comments')
function(data) {
var result = '',
len = data.length,
i=0;
for(;i<len;i++) {
result += data[i]['comment_text'] +'<br />'
}
return result;
}
Here is a implementation into the origin function. I post this cause the use of Ext.Array.each is not recommend, because it executes a function for each element and functioncalls within loops should be spared.
showPost: function(list, index, element, record) {
var data = record.get('comments');
function fetchComments(data) {
var result = '',
len = data.length,
i = 0;
for(;i<len;i++) {
result += data[i]['comment_text'] + '<br />';
}
return result;
}
this.getStream().push({
xtype: 'panel',
html: [
'<p>' + record.get('post_thumb') + '</p>',
'<p>' + fetchComments(data) + '</p>'
].join(''),
scrollable: true,
styleHtmlContent: true,
});
}
Here is the other way I have iterated.
Json data:
{
"account" : [
{
"id": "1",
"accNo" : "5869785254",
"curAmt" : "25000",
"balAmt" : "15000",
"transdate" : [
{
"date" : "10",
"month" : "03",
"description" : "Check 232",
"crddbt" : "-1200"
},
{
"date" : "14",
"month" : "03",
"description" : "ATM Withdrawl",
"crddbt" : "-500"
}
],
}
]
}
Sencha Code to iterate on transdate object.
var transDateObj = record.get('transdate');
Ext.Object.each(transDateObj, function(key, value, myself){
Ext.Object.each(value, function(key, value, myself){
console.log(key + ":" + value);
});
});