json to load values into extjs checkboxgroup grid editor - json

I need to set up a CheckboxGroup checkboxes with values loaded with json from some url.
What is a correct format of JSON?
Many thanks for help!
Update: I'll clarify my problem.
I'm using EditorGridPanel. Rows are Periods. There are columns Start_at, Finish_at, Region. First and second are date and everything ok with them. Problem with Region which actually is a CheckboxGroup with a checkbox for each week day - Monday, Tuesday, etc. So:
First I'm loading data from server into store
function setupDataSource() {
row = Ext.data.Record.create([
{ name: 'start_at', type: 'string' },
{ name: 'finish_at', type: 'string' },
{ name: 'region', type: 'string' }
]);
store = new Ext.data.Store({
url: '/country/195/periods',
reader: new Ext.data.JsonReader(
{
root: 'rows',
id: 'id'
},
row
)
});
store.load();
}
URL url: '/country/195/periods' returns JSON:
{"rows": [{"region": {"cbvert_1": 1, "cbvert_2": 0, "cbvert_3": 1, "cbvert_4": 0, "cbvert_5": 1, "cbvert_6": 0, "cbvert_7": 1}, "start_at": "2010-10-17", "id": 1, "finish_at": "2010-10-28"}]}
Then I'm building a grid:
function buildGrid() {
sm = new Ext.grid.RowSelectionModel();
cm = new Ext.grid.ColumnModel([
// ... Start at and Finish at columns definition here ...
{ header: 'Region',
dataIndex: 'region',
width: 150,
editor: new Ext.form.CheckboxGroup({
xtype: 'checkboxgroup',
columns: 7,
vertical: true,
items: [
{boxLabel: 'M', name: 'cbvert_1', inputValue: 1},
{boxLabel: 'T', name: 'cbvert_2', inputValue: 1},
{boxLabel: 'W', name: 'cbvert_3', inputValue: 1},
{boxLabel: 'T', name: 'cbvert_4', inputValue: 1},
{boxLabel: 'F', name: 'cbvert_5', inputValue: 1},
{boxLabel: 'S', name: 'cbvert_6', inputValue: 1},
{boxLabel: 'S', name: 'cbvert_7', inputValue: 1},
]
}),
renderer: function(value) {}
}]);
// ...
}
So, when I'm clicking on a grid cell I need to get checkboxes preselected with values previously stored in database. Now all checkboxes are stay blank but should be 1010101 as its in JSON.
Please point me to errors or maybe a some kind of a solution. Any help will be greatly appreciated.
Many thanks!

Check this out:
http://www.sencha.com/forum/showthread.php?47243-Load-data-in-checkboxgroup
Updated:
Remove the type declaration of the region field. You do not need a string but an object (from JSON). It works just fine that way :)

Related

Quey Post and comments and User with MySql and knex [duplicate]

I have a heavy array like this:
[
{Id: 1, Name: 'Red', optionName: 'Color'},
{Id: 2, Name: 'Yellow', optionName: 'Color'},
{Id: 3, Name: 'Blue', optionName: 'Color'},
{Id: 4, Name: 'Green', optionName: 'Color'},
{Id: 7, Name: 'Black', optionName: 'Color'},
{Id: 8, Name: 'S', optionName: 'Size'},
{Id: 11, Name: 'M', optionName: 'Size'},
{Id: 12, Name: 'L', optionName: 'Size'},
{Id: 13, Name: 'XL', optionName: 'Size'},
{Id: 14, Name: 'XXL', optionName: 'Size'}
]
What I need to do is to group them by optionName and have two row in the main array like this:
[
{
Name: 'Color',
Data:[{Id: 1, Name: 'Red'},
{Id: 2, Name: 'Yellow'},
{Id: 3, Name: 'Blue'},
{Id: 4, Name: 'Green'},
{Id: 7, Name: 'Black'}]
}, {
Name: 'Size',
Data:[{Id: 8, Name: 'S'},
{Id: 11, Name: 'M'},
{Id: 12, Name: 'L'},
{Id: 13, Name: 'XL'},
{Id: 14, Name: 'XXL'}]
}
]
How to do it in javascript?
This is a snippet I wrote for these kind of situations. You can add this functionality to all of your arrays:
Object.defineProperty(Array.prototype, 'group', {
enumerable: false,
value: function (key) {
var map = {};
this.forEach(function (e) {
var k = key(e);
map[k] = map[k] || [];
map[k].push(e);
});
return Object.keys(map).map(function (k) {
return {key: k, data: map[k]};
});
}
});
You can use it like this. You can just pass a function which defines how you want to group your data.
var newArray = arr.group(function (item) {
return item.optionName;
});
Working Fiddle
If you need, you can replace {key: k, data: map[k]} with {Name: k, Data: map[k]}.
This is also more compact ES6 version of the code above:
Object.defineProperty(Array.prototype, 'group', {
enumerable: false,
value: function (key) {
let map = {};
this.map(e => ({k: key(e), d: e})).forEach(e => {
map[e.k] = map[e.k] || [];
map[e.k].push(e.d);
});
return Object.keys(map).map(k => ({key: k, data: map[k]}));
}
});
Use it like this:
let newArray = arr.group(item => item.optionName))
An ES6 solution using Map object:
function groupBy(arr, key) {
return arr.reduce(
(sum, item) => {
const groupByVal = item[key];
groupedItems = sum.get(groupByVal) || [];
groupedItems.push(item);
return sum.set(groupByVal, groupedItems);
},
new Map()
);
}
var Data = [
{ Id: 1, Name: 'Red', optionName: 'Color' },
{ Id: 2, Name: 'Yellow', optionName: 'Color' },
{ Id: 3, Name: 'Blue', optionName: 'Color' },
{ Id: 4, Name: 'Green', optionName: 'Color' },
{ Id: 7, Name: 'Black', optionName: 'Color' },
{ Id: 8, Name: 'S', optionName: 'Size' },
{ Id: 11, Name: 'M', optionName: 'Size' },
{ Id: 12, Name: 'L', optionName: 'Size' },
{ Id: 13, Name: 'XL', optionName: 'Size' },
{ Id: 14, Name: 'XXL', optionName: 'Size' } ];
document.getElementById("showArray").innerHTML =JSON.stringify([...groupBy(Data, 'optionName')], null, 4);
<pre id="showArray"></pre>
You can use reduce to get the resultset you need:
var result = list.reduce(function(memo, item) {
if (item.optionName === 'Color') {
memo[0].Data.push(
Id: item.Id,
Name: item.Name
});
}
if (item.optionName === 'Size') {
memo[1].Data.push({
Id: item.Id,
Name: item.Name
});
}
return memo;
}, [{ Name: 'Color', Data: [] }, { Name: 'Size', Data: [] }]);
variable list is your first list.
Hope this helps.
This is a snippet I wrote for kind of my situation in my application functionality of all arrays. This snippet code is use in node js application. All the above is is given solution but I was finding some problem in server side in node js.
This snippet is user full me....
var Data= [
{ Id: 1, Name: 'Red', optionName: 'Color' },
{ Id: 2, Name: 'Yellow', optionName: 'Color' },
{ Id: 3, Name: 'Blue', optionName: 'Color' },
{ Id: 4, Name: 'Green', optionName: 'Color' },
{ Id: 7, Name: 'Black', optionName: 'Color' },
{ Id: 8, Name: 'S', optionName: 'Size' },
{ Id: 11, Name: 'M', optionName: 'Size' },
{ Id: 12, Name: 'L', optionName: 'Size' },
{ Id: 13, Name: 'XL', optionName: 'Size' },
{ Id: 14, Name: 'XXL', optionName: 'Size' } ];
function groupBy(arr, key) {
var newArr = [],
types = {},
newItem, i, j, cur;
for (i = 0, j = arr.length; i < j; i++) {
cur = arr[i];
if (!(cur[key] in types)) {
types[cur[key]] = { type: cur[key], data: [] };
newArr.push(types[cur[key]]);
}
types[cur[key]].data.push(cur);
}
return newArr;
}
I use it like this. I just pass a function which defines how you want to group our data.
filterData= groupBy(Data,'optionName');
Result of this snippet of code output.....
[
{"type":"Color","data":[{"Id":1,"Name":"Red","optionName":"Color"},
{"Id":2,"Name":"Yellow","optionName":"Color"},
{"Id":3,"Name":"Blue","optionName":"Color"},
{"Id":4,"Name":"Green","optionName":"Color"},
{"Id":7,"Name":"Black","optionName":"Color"}]},
{"type":"Size","data":[{"Id":8,"Name":"S","optionName":"Size"},
{"Id":11,"Name":"M","optionName":"Size"},
{"Id":12,"Name":"L","optionName":"Size"},
{"Id":13,"Name":"XL","optionName":"Size"},
{"Id":14,"Name":"XXL","optionName":"Size"}]}
]
Show on fiddle
var originalList = [ { Id: 1, Name: 'Red', optionName: 'Color' },
{ Id: 2, Name: 'Yellow', optionName: 'Color' },
{ Id: 3, Name: 'Blue', optionName: 'Color' },
{ Id: 4, Name: 'Green', optionName: 'Color' },
{ Id: 7, Name: 'Black', optionName: 'Color' },
{ Id: 8, Name: 'S', optionName: 'Size' },
{ Id: 11, Name: 'M', optionName: 'Size' },
{ Id: 12, Name: 'L', optionName: 'Size' },
{ Id: 13, Name: 'XL', optionName: 'Size' },
{ Id: 14, Name: 'XXL', optionName: 'Size' } ];
var output = [{ Name: "Color", Data: [] },{ Name: "Size", Data: [] }] ;
originalList.map(function(entry){
if ( entry.optionName === "Color") output[0].Data.push({ Id: entry.Id, Name: entry.Name });
if ( entry.optionName === "Size") output[1].Data.push({ Id: entry.Id, Name: entry.Name });
});
'use strict'
let l = [ { Id: 1, Name: 'Red', optionName: 'Color' },
{ Id: 2, Name: 'Yellow', optionName: 'Color' },
{ Id: 3, Name: 'Blue', optionName: 'Color' },
{ Id: 4, Name: 'Green', optionName: 'Color' },
{ Id: 7, Name: 'Black', optionName: 'Color' },
{ Id: 8, Name: 'S', optionName: 'Size' },
{ Id: 11, Name: 'M', optionName: 'Size' },
{ Id: 12, Name: 'L', optionName: 'Size' },
{ Id: 13, Name: 'XL', optionName: 'Size' },
{ Id: 14, Name: 'XXL', optionName: 'Size' } ];
let color = [];
let size = [];
l.forEach(element => {
if (element['optionName'] === 'Color') {
color.push({'Id': element.Id, 'Name': element.Name});
} else {
size.push({'Id': element.Id, 'Name': element.Name});
}
});
console.log(color);
console.log(size);
You can try this method.
All of the answers lead to the same result, so it all comes down to a personal preference (or company guidelines) on how to tackle this.
// ES5 (traditional javascript) version
function groupByOptionName(list, optionName) {
return list
// filter out any item whose optionName does not match the desired name
.filter(function(item) {
return item.optionName === optionName;
})
// map the item into the desired shape
// (appears to be everything except optionName itself
.map(function(item) {
return {
Id: item.Id,
Name: item.Name
};
})
}
// ES2015/ES6 version
function groupByOptionName(list, optionName) {
return list
// filter out any item whose optionName does not match the desired name
.filter(item => item.optionName === optionName)
// map the item into the desired shape
// (appears to be everything except optionName itself
.map(item => {
Id: item.Id,
Name: item.Name
});
}
This function would let you program the desired result as follows:
var output = [
{Name: 'Color', Data: groupByOptionName(list, 'Color')},
{Name: 'Size', Data: groupByOptionName(list, 'Size')},
];
// the ES2015/ES6 version of this code would replace var with let
While the code itself differs, it is much like the other answers, with only a variation on the steps needed.
One could also opt to leave out any hardcoded option names (Color and Size) by extracting those aswel, this would allow for a more dynamic input, but could also introduce more processing that actually needed.
// ES5 (traditional javascript) version
function getOptionNames(list) {
return list
// map the array into a list of optionNames
.map(function(item) {
return item.optionName;
})
// remove duplicates
.filter(function(item, index, all) {
return all.indexOf(item) === index;
});
}
// ES2015/ES6 version (does exactly the same as the one above)
function getOptionNames(list) {
return list
// map the array into a list of optionNames
.map(item => item.optionName)
// remove duplicates
.filter((item, index, all) => all.indexOf(item) === index);
}
Which allows the result to be fully based on the input data:
// ES5 (traditional javascript) version
var output = getOptionNames(list)
// map the names into the desired structure
.map(function(buffer, name) {
return {
Name: name,
Data: groupByOptionName(list, name)
};
});
// ES2015/ES6 version (does exactly the same as the one above)
var output = getOptionNames(list)
// map the names into the desired structure
.map((buffer, name) => {
Name: name,
Data: groupByOptionName(list, name)
});
By writing all of the data-mangling steps in short consice steps you'd do yourself (especially your future self) a favor if this code ever needs to be adjusted.
If the data set really is heavy (in terms of a lot of data), you must also make sure to keep the number of copies you keep in memory limited. For example, if you never need the original dataset, make sure it can be garbage collected (by not having a variable containing it outside the scope where you receive the data)
Usage:
groupValues([
{ color: 'blue', value: 100 },
{ color: 'blue', value: 75 },
{ color: 'yellow', value: 50 },
{ color: 'yellow', value: 25 }
], 'color')
Result:
[
[{ color: 'blue', value: 100 }, { color: 'blue', value: 75 }],
[{ color: 'yellow', value: 50 }, { color: 'yellow', value: 25 }]
]
Function:
const groupValues = function(arr, key) {
const mapped = {}
arr.forEach(el => {
const actualKey = el[key]
if(!mapped.hasOwnProperty(actualKey)) mapped[actualKey] = []
mapped[actualKey].push(el)
})
return Object.keys(mapped).map(el => mapped[el])
}

Subtract Expression JSON

Update: I am trying to do subtract expression in JSON file.
export const PRODUCTS: Products[] = [
{
id: 1,
productCat:'Product Cat',
product: [
{
productName: 'Product Name',
newPrice: 800,
oldPrice: 1000,
save: 'oldPrice' - 'newPrice'
},
],
}
]
I am new to JSON so I dont know if it's even possible. If there is any other way please help.
Use forEach function to add save key. like this
const PRODUCTS = [{
id: 1,
productCat: 'Product Cat',
product: [{
productName: 'Product Name',
newPrice: 800,
oldPrice: 1000
},
{
name: 'Product Name 2',
newPrice: 1800,
oldPrice: 10000
}
],
}];
PRODUCTS[0].product.forEach(itm => itm['save'] = itm['oldPrice'] - itm['newPrice']);
console.log(PRODUCTS);

kendoui json fill datagrid

This works fine, filling grid:
$("#grid").kendoGrid({
dataSource: {
data: [
{'id': 1, 'name': 2, 'author': 3},
{'id': 1, 'name': 2, 'author': 3},
{'id': 1, 'name': 2, 'author': 3},
] ,
},
but when I load list from getJSON:
$.getJSON('/api/notes/', function(data) {
dataSource = data.rows;
});
Pointing data to dataSource array nothing is displayed :(
If received data is in data.rows, you should do:
$("#grid").data("kendoGrid").dataSource.data = data.rows;
But, why do you not use transport.read in the grid.dataSource for loading data instead of using getJSON?
You should use the data method of the dataSource.
e.g.
$.getJSON('/api/notes/', function(data) {
dataSource.data(data.rows);
});

Dojo how to get JSON attribute from dojo.data.ItemFileReadStore

I have the below JSON in the typeData variable that is then put into a dojo.data.ItemFileReadStore. What I need to know is how to check the value of status, was it set to "success" or some other value. I've not been able to figure out how to get the value of status from a ItemFileReadStore, any help would be greatly appreciated.
var typesData = {
status: "success",
label: "name",
identifier: "value",
items: [
{value: 3, name: "Truck"},
{value: 8, name: "Van"},
{value: 6, name: "Car"},
{value: 7, name: "Scooter"}
]
};
var test = new dojo.data.ItemFileReadStore({ data: typesData });
The ItemFileReadStore will not handle additional attributes on the data object. However, you can extend the ItemFileReadStore to do what you need. You will be overriding 'internal' methods, so it's developer beware.
dojo.declare("MyCustomStore", [Store], {
_getItemsFromLoadedData: function(/* Object */ dataObject){
this.serverStatus = dataObject.status;
this.inherited(arguments);
}
});
var typesData = {
status: "success",
label: "name",
identifier: "value",
items: [
{value: 3, name: "Truck"},
{value: 8, name: "Van"},
{value: 6, name: "Car"},
{value: 7, name: "Scooter"}
]
};
var test = new MyCustomStore({ data: typesData });
test._forceLoad(); // forces the processing of the data object
console.debug(test.serverStatus);
http://jsfiddle.net/cswing/dVGSc/

How can I use a Ext JsonReader to return a Master Detail record set?

Let's say I have an invoice and an invoice item. I'd like to show a list of invoices in a grid on the top and below I want to show the corresponding invoice items to the selected invoice. I have the SQL and JSON part down fine. I query the invoices, query the invoices items for all invoices returned (only 2 queries). Then I match up the items with their invoices. And finally I convert this into JSON. It would look something like this.
{
"success": true,
"results": 2,
"rows": [
{
"data": {"id": 1, "invoiceDate": "2010-01-01", "total": "101.00" },
"invoiceItems": [
{"id": 11, "invoiceID": 1, "item": "baseball", "subtotal": "50.00" },
{"id": 12, "invoiceID": 1, "item": "bat", "subtotal": "51.00" }
]
},
{
"data": {"id": 2, "invoiceDate": "2010-02-02", "total": "102.00" },
"invoiceItems": [
{"id": 21, "invoiceID": 2, "item": "hat", "subtotal": "52.00" },
{"id": 22, "invoiceID": 2, "item": "baseball", "subtotal": "50.00" }
]
}
]
}
So when I select invoice 1 in the top grid, I want to see items 11 and 12 displayed in the botton grid. And then show 21 and 22 when invoice 2 is selected. I'd like to NOT have to return to the server every time I toggle between invoices.
And then finally, I'd love to be able to track which ones have changes so that I can send data back to be persisted.
How is this all possible using Ext JS? I've yet to see a working master detail example using Ext JS.
This is certainly possible with ExtJS and I suggest ExtJS provides tools to help.
However, you might be encountering trouble if you are trying to use a single store to contain your JSON records. I recall reading (I searched for a reference, but was unable to find it) you should think of a store as a single database table rather than trying to store parent/child information in one store.
So, I humbly suggest you store your invoices in one store and your invoice items in a second store, link the child invoice items to the parent invoice via some reference (invoice ID), and use these two stores to support two different grids (or whatever widget) - one for invoices and a second for invoice items. When a user clicks on an invoice, your listener (event handler) would update the invoice items grid/widget appropriately.
This would be my approach.
in that case, you need two readers as code below:
var reader2 = new Ext.data.JsonReader({
root: 'invoiceItems',
fields: [{name: 'id', type:'int'},
{name: 'invoiceID', type:'int'},
{name: 'item', type:'string'},
{name: 'subtotal': type:'float'}]
});
var reader = new Ext.data.JsonReader({
idProperty: 'id',
totalProperty: 'results',
successProperty: "success",
root: 'rows',
fields: [
{name: 'id', type:'int'},
{name: 'invoiceDate', type:'date'},
{name: 'total', type:'float'},
{name: 'invoiceItems', convert: function(v, n){ return reader2.readRecords(n).records;} }//v: value, n: data;
]
});
var conn = new Ext.data.Connection({
timeout : 120000,
url: 'address-path-to-get-json-data',
method : 'POST'
});
var dproxy = new Ext.data.HttpProxy(conn);
var gstore = new Ext.data.Store({
proxy: dproxy,
reader: reader,
sortInfo:{field: 'id', direction: "DESC"}
});
and here is code you need to render the grid
var numrender = function(value, cell, rec, rowIndex, colIndex, store){
if(value*1>0){
return Ext.util.Format.number( value, '0,000.00');
}else return '-';
}
var invoicedetail = function(value, cell, rec, rowIndex, colIndex, store) {
var html = '<div class="itemdetail">{0} - {1} - {2} - {3}</div>';
var re = '';
Ext.each(value,function(item,index){
re += String.format(html,item.get('id'),item.get('invoiceID'),item.get('item'),item.get('subtotal'));
});
return re;
}
var cm = [
new Ext.grid.RowNumberer({header:"No.", width: 30}),
{header: "ID", align: 'left',sortable:true, width: 40, dataIndex: 'id'},
{header: "Invoice Date", align: 'left',sortable:true, width: 40, dataIndex: 'invoiceDate'},
{header: "Total", align: 'right', width: 30, dataIndex: 'total', renderer: numrender},
{header: "Invoice Items", align: 'left',sortable:false, id:'col_detail', width: 100, dataIndex: 'invoiceItems', renderer: invoicedetail}
];
var grid = new Ext.grid.GridPanel({
id:'invoices',
store: gstore,
columns: cm,
enableHdMenu: false,
loadMask: {msg:'Loading Invoices ...'},
enableColumnResize:false,
stripeRows: true,
viewConfig: { autoFill: true },
columnLines : true,
autoExpandColumn: 'col_detail',
renderTo:'grid-wrapper'
});
gstore.load();
or you might be interested in looking at this treegrid:
http://www.max-bazhenov.com/dev/ux.maximgb.tg/index.php
This is certainly possible however you aren't really mapping the sub-objects rather than just expecting them to be there...
Consider this test case (stick it into FireBug and you should see the results..)
var store = new Ext.data.JsonStore({
data: {
success: true, result: [
{
test: {prop1: 1, prop2: 2}
}]
},
root: 'result',
fields: ['test']
});
console.log(store.getRange()[0].data.test.prop1); // prints "1"
In your instance you would do something like this in your row select event...
//assume "this" = your panel containing your Grid (at position 0) and another Grid (at position 1)
var selectedRowRecord = this.get(0).getSelectionModel().getSelected();
var invoiceItemsStore = this.get(1).getStore();
invoiceItemsStore.removeAll();
invoiceItemsStore.loadData(selectedRowRecord.data.invoiceItems);
Hope this helps.
Stuart