Being very new to Kendo UI and Knockout (3 days!), I'm trying to convert a legacy Java applet to Javascript. So far, creating and binding the kendoGrid was relatively easy:
function JobViewModel() {
var self = this;
self.jobData = new ko.observableArray([]);
self.grdJobs = {
scrollable: true,
sortable: true,
filterable: false,
columnMenu: true,
resizable: true,
columns: [
{ title: "Job ID", field: "jobID" },
{ title: "Owner", field: "owner" },
{ title: "Description", field: "description" },
{ title: "State", field: "runState" },
{ title: "Start Time", field: "timeStart" },
{ title: "End Time", field: "timeEnd" },
{ title: "Elapsed Time", field: "timeElapsed" },
{ title: "Progress", field: "progress" },
{ title: "Agent", field: "agent" },
{ title: "Last Action", field: "lastAction" }
],
selectable: "single"
};
};
The data coming back from the server are an array of JSON objects (of any length) something like the following (shortened for brevity):
[{0: 1, 2: 3, 4: 5, ...}, {0: 1, 2: 21, 4: 5, ...}, {0: 1, 2: 23, 4: 5, ...}]
This array of objects which are numeric key/value pairs are mapped to a dictionary object where the numeric keys are paired with string values something like:
{
0: "State"
1: "Finished"
2: "JOB ID"
3: "54759"
4: "Owner"
5: "John"
...
21: "54758"
...
23: "54757"
...
}
What I need to get is the mapped strings from the dictionary as they relate to the array of JSON objects. The approach I tried was to JSON.stringify(obj[i]) but then I wasn't sure what I could do with it (maybe use it in a ko.observable that could be assigned to the kendoGrid?) Anyway, what I'm after based on the sample data I've shown above is a grid with column headers "JOB ID", "Owner", and "State" and 3 rows of jobs (54757, 54758, 54759) all owned by John and State Finished.
I hope this all made sense. I guess what I really need is how to take JSON and convert it into something usable that can be populated into a Kendo Grid. Thanks for helping out a JS/JSON/Kendo/Knockout neophyte!
You could try to map those two arrays you have to another array with elements you can use.
I made a simple jsFiddle to demonstrate this: jsFiddle
The code is pretty straight forward:
var data = [{ 0: 1, 2: 3 }, { 0: 4, 2: 3 }];
var mapping = { 0: 'State', 1: 'Finished', 2: 'Owner', 3: 'John', 4: 'Pending' };
var realData = [];
$.each(data, function(index, obj) {
var arrayElem = {};
$.each(obj, function(key, value) {
arrayElem[mapping[key]] = mapping[value];
});
realData.push(arrayElem);
});
Related
Been trying to do the following thing:
I have an array of objects ,
var arr = [
{ key: "aabFaa", text: "aabFaa" ,field: "firstName",checked: true},
{ key: "aAaaaa", text: "aAaaaa", field: "firstName", checked: true },
];
Would want to fetch the "text" and "field" out of it and form a new array of objects something like this:
result = [ { "field" : "firstName" , value : "aabFaa" , type :"add"},
{ "field" : "firstName" , value : "aAaaaa" , type: "add"}
]
Here type is hard coded one, where as rest are fetched from the "arr"
Whats the easier way to do this?
Have tried this:
var arr = [
{ key: "aabFaa", text: "aabFaa" ,field: "firstName",checked: true},
{ key: "aAaaaa", text: "aAaaaa", field: "firstName", checked: true },
];
let result = arr.map(a => a.text);
console.log(result)
But this has to be written in multiple lines to get desired properties.Is there an easier approach?
use map with Object Destructuring.
var arr = [
{ key: "aabFaa", text: "aabFaa" ,field: "firstName",checked: true},
{ key: "aAaaaa", text: "aAaaaa", field: "firstName", checked: true },
];
const output = arr.map(({field, text}) => ({field, value: text, type: "add"}));
console.log(output);
Using map seems like a good approach, but you would return a new object and not just one property:
let result = arr.map(a => ({value: a.text, type: 'add', field: a.field}));
let result = arr.map(obj => ({
field: obj.field,
value: obj.text,
type: "add"
}));
I have an issue with manipulating data in Javascript/jQuery and I could use some help.
I have an array of objects that lools like this:
var projects = [
{title:'project1'},
{title:'project2'},
{title:'project3'},
];
I have another array of objects that looks like this:
ganttEvents = [
{
text: 'some text',
start_date: '2018/06/13',
end_date: '2018/06/14',
id: '1',
readonly: true,
project: 'project1',
category: 'scoping',
}
{
text: 'some text2',
start_date: '2018/06/14',
end_date: '2018/06/15',
id: '1',
readonly: true,
project: 'project2',
category: 'scoping',
}
{
text: 'some text3',
start_date: '2018/06/15',
end_date: '2018/06/16',
id: '1',
readonly: true,
project: 'project2',
category: 'design',
}
{
text: 'some text4',
start_date: '2018/06/13',
end_date: '2018/06/14',
id: '1',
readonly: true,
project: 'project2',
category: 'scoping',
}
{
text: 'some text5',
start_date: '2018/06/14',
end_date: '2018/06/15',
id: '1',
readonly: true,
project: 'project3',
category: 'testing',
}
{
text: 'some text6',
start_date: '2018/06/15',
end_date: '2018/06/16',
id: '1',
readonly: true,
project: 'project3',
category: 'build',
}
];
The project field in the second object will always be one of the objects in the first array.
I then need to end up with an object that looks like this:
source: [
{
name: "project1", // a project defined in the projects array
desc: "scoping", // the category from the ganttEvents array of objects
values: [
{
to: "2018/06/13", // the start_date from the ganttEvents array of objects
from: "2018/06/14", // the end_date from the ganttEvents array of objects
desc: "some text", // the text from the ganttEvents array of objects
label: "some text", // the text from the ganttEvents array of objects
}
]
},
{
name: "project2", // a project defined in the projects array
desc: "scoping", // the category from the ganttEvents array of objects
values: [
{
to: "2018/06/14",
from: "2018/06/15",
desc: "some text2",
label: "some text2",
},
{
to: "2018/06/13",
from: "2018/06/14",
desc: "some text4",
label: "some text4",
},
]
},
{
name: "project3", // a project defined in the projects array
desc: "testing", // the category from the ganttEvents array of objects
values: [
{
to: "2018/06/14",
from: "2018/06/15",
desc: "some text5",
label: "some text5",
}
]
},
{
name: "project3", // a project defined in the projects array
desc: "build", // the category from the ganttEvents array of objects
values: [
{
to: "2018/06/15",
from: "2018/06/16",
desc: "some text6",
label: "some text6",
}
]
},
]
There may be several values at all stages for each project and there maybe projects with no events at all that need to be omitted from the source object.
Please can you assist?
Edit:
The background behind this is that I am pulling a list of events from a SharePoint list using SharePointPlus. This results in the ganttEvents array. I need to plug this in to the jQuery.Gantt library which requires the events to be formatted in a particular way.
jQuery.Gantt
I am sorry but i am relatively new to Javascript (Python programmer usually) I have tried different methods of doing this to no avail.
You can use reduce to group the array into an object. Use the concatenated values of project and category as the key. Use Object.values to convert the object into an array.
var ganttEvents = [{"text":"some text","start_date":"2018/06/13","end_date":"2018/06/14","id":"1","readonly":true,"project":"project1","category":"scoping"},{"text":"some text2","start_date":"2018/06/14","end_date":"2018/06/15","id":"1","readonly":true,"project":"project2","category":"scoping"},{"text":"some text3","start_date":"2018/06/15","end_date":"2018/06/16","id":"1","readonly":true,"project":"project2","category":"design"},{"text":"some text4","start_date":"2018/06/13","end_date":"2018/06/14","id":"1","readonly":true,"project":"project2","category":"scoping"},{"text":"some text5","start_date":"2018/06/14","end_date":"2018/06/15","id":"1","readonly":true,"project":"project3","category":"testing"},{"text":"some text6","start_date":"2018/06/15","end_date":"2018/06/16","id":"1","readonly":true,"project":"project3","category":"build"}];
var result = Object.values(ganttEvents.reduce((c, v) => {
let k = v.project + "-" + v.category;
c[k] = c[k] || {name: v.project,desc: v.category,values: []};
c[k].values.push({to: v.end_date,from: v.start_date,desc: v.text,label: v.text});
return c;
}, {}));
console.log(result);
Without Object.values(), you can loop using for
var ganttEvents = [{"text":"some text","start_date":"2018/06/13","end_date":"2018/06/14","id":"1","readonly":true,"project":"project1","category":"scoping"},{"text":"some text2","start_date":"2018/06/14","end_date":"2018/06/15","id":"1","readonly":true,"project":"project2","category":"scoping"},{"text":"some text3","start_date":"2018/06/15","end_date":"2018/06/16","id":"1","readonly":true,"project":"project2","category":"design"},{"text":"some text4","start_date":"2018/06/13","end_date":"2018/06/14","id":"1","readonly":true,"project":"project2","category":"scoping"},{"text":"some text5","start_date":"2018/06/14","end_date":"2018/06/15","id":"1","readonly":true,"project":"project3","category":"testing"},{"text":"some text6","start_date":"2018/06/15","end_date":"2018/06/16","id":"1","readonly":true,"project":"project3","category":"build"}];
var temp = ganttEvents.reduce((c, v) => {
let k = v.project + "-" + v.category;
c[k] = c[k] || {name: v.project,desc: v.category,values: []};
c[k].values.push({to: v.end_date,from: v.start_date,desc: v.text,label: v.text});
return c;
}, {});
var result = [];
for (var key in temp) result.push(temp[key]);
console.log(result);
I have my data as following:
{
meta: {
format: "csv",
info: "desc",
columns: [
{
id: "Name",
type: "Text",
length: 32
},
{
id: "Text",
type: "Text",
length: 128
}]
},
rows: [
["John","xxxx"],
["Alpha","yyyy"],
["Beta","wwww"],
["Gamma","zzzz"]]
}
Now, I am struggling to map the records to a Table control as Columns and Rows. Column seems straight forward, straight map, but the rows since lacks a mapping to column I wonder what could be the simplest way.
Approach Steps:
Make a keys[] from column.id of each columns record.
Traverse the rows[]
Each loop, while keys.length create an object as {keys[j]:row[k]}
Push to an array
Recreate the original JSON but replace Rows arrays with Objects
I am really struggling to translate this into code specially at the rows[] parsing and creating Objects. Is there, I am sure there must be, an efficient way to achieve this.
Here is what you could do. using Array.map and forEach.
var input = {
meta: {
format: "csv",
info: "desc",
columns: [{
id: "Name",
type: "Text",
length: 32
}, {
id: "Text",
type: "Text",
length: 128
}]
},
rows: [
["John", "xxxx"],
["Alpha", "yyyy"],
["Beta", "wwww"],
["Gamma", "zzzz"]
]
};
var columns = input.meta.columns.map((column) => {
return column.id
});
var rows = input.rows.map((row) => {
var obj = {};
row.forEach((column, idx) => {
obj[columns[idx]] = column;
});
return obj;
});
input.rows = rows;
console.log(input);
I'm trying to display data in a stacked graph using kendo ui. Here is my code:
var data = [
// June
{ Start: "2014-06-01T00:00:00", Name : "Series 1", Value: 1 },
{ Start: "2014-06-01T00:00:00", Name : "Series 2", Value: 2 },
{ Start: "2014-06-01T00:00:00", Name : "Series 3", Value: 10 },
// July
{ Start: "2014-07-01T00:00:00", Name : "Series 1", Value: 2 },
{ Start: "2014-07-01T00:00:00", Name : "Series 2", Value: 2 },
{ Start: "2014-07-01T00:00:00", Name : "Series 3", Value: 2 },
// August
{ Start: "2014-08-01T00:00:00", Name : "Series 1", Value: 3 },
{ Start: "2014-08-01T00:00:00", Name : "Series 2", Value: 2 },
{ Start: "2014-08-01T00:00:00", Name : "Series 3", Value: 1 },
// September
{ Start: "2014-09-01T00:00:00", Name : "Series 2", Value: 2 },
{ Start: "2014-09-01T00:00:00", Name : "Series 3", Value: 3 },
// October
{ Start: "2014-10-01T00:00:00", Name : "Series 1", Value: 1 },
{ Start: "2014-10-01T00:00:00", Name : "Series 3", Value: 3 }
]
var stocksDataSource = new kendo.data.DataSource({
data: data,
group: {
field: "Name"
},
sort: [{ field: "Start", dir: "asc"} ]
});
function createChart() {
$("#chart").kendoChart({
dataSource: stocksDataSource,
series: [{
type: "column",
field: "Value",
name: "#= group.value #",
stack: true,
tooltip: {
template: "#=kendo.toString(new Date(category), 'd MMM yyyy')#<br/>" +
"#=dataItem.Name#<br/>"+
"Value: #=dataItem.Value#",
visible: true
},
}],
categoryAxis: {
field: "Start",
type: "date",
labels: {
format: "MMM"
}
}
});
}
$(document).ready(createChart);
$(document).bind("kendo:skinChange", createChart);
Note that September and October data do not have values for some series. This completely screws up the chart display in quite unexplainable way:
As you can see both September and October data do not match the json. It's especially weird with October data because three values are displayed whereas only 2 are given.
Here is JSFiddle: http://jsfiddle.net/12ob7qmx/6/
Are there any settings on the chart that I can set so it works, or will I have to loop through the dataset and fill in missing data with zero values?
The way I solved this issue is by looping through my data and adding missing values with 0's.
I don't think there is a better way, than what you suggested yourself. :(
I found a question concerning this issue on the Telerik forums:
The behavior you have observed is expected as the categorical charts
(bar, area etc.) require a matching set of data points (the value can
be null but it should persist in the data). I am afraid there is no
built-in functionality which will automatically set 0 for the missing
values - you should modify your data.
I am afraid the implementation of this functionality is not in our immediate plans, however we may consider it for future versions of the product.
I haven't found more recent information, but as far as I know this hasn't been fixed.
It' looks like I'm out of luck and I need to fix up the data. In my actual solution I'm doing that server-side, but for posterity if anyone needs a kickstart with a purely js fix, this is the starting point:
function fixData(data) {
var lookup =[], start = [], name = [], result =[];
for (i = 0, len = data.length; i < len; ++i) {
start[data[i].Start] = true;
name[data[i].Name] = true;
lookup[data[i].Start + "," + data[i].Name] = data[i].Value;
}
for (var currentStart in start) {
for (var currentName in name) {
var entry = {Start: currentStart, Name: currentName};
entry.Value = lookup[currentStart + "," + currentName] || 0;
result.push(entry);
}
}
return result;
}
JSFiddle: http://jsfiddle.net/12ob7qmx/8/
I have following data Structure which I want to use in data structure given in Dyntree Format:
[
{
title: "my Title",
isFolder: "true",
key: 1
}
]
I am setting above data structure as STRING in a JS variable.
When I set this value as a javascript variable, it gives error of Invalid Type
DynTree format is given below;
var fakeJsonResult = [
{ title: 'Lazy node 1', isLazy: true },
{ title: 'Simple node 2', select: true }
];
This is simple if you want to create a dynatree from the object you mentioned simply do this
var children = [
{
title: "my Title",
isFolder: "true",
key: 1
}
];
$('#tree').dynatree({
children : children
});