I am trying to create a grouped bar chart using Observable's Plot.plot in JavaScript (code is in TypeScript).
The problem is that the x-axis is showing each specific date, however I want the dates to show dynamic months or weeks, not specific dates.
This is the code:
const chart = Plot.plot({
x: { axis: null, domain: ["Add", "Remove"], },
y: { tickFormat: "s", label: "↑ Access Requests", grid: true },
color: {
legend: true,
type: "categorical",
domain: ["Add", "Remove"],
range: redGreenColorRange,
},
style: {
background: "transparent",
},
width: 1350,
caption: "in 2 week increments",
facet: {
data: groupedAddRemove,
label: "Created Date",
x: "createdDate",
// thresholds: d3.utcWeeks,
// ^ this doesn't work, but a similar structure has worked in other projects I've seen
},
marks: [
Plot.barY(groupedAddRemove, {
x: "type",
y: "count",
fill: "type",
}),
Plot.ruleY([0]),
],
});
and this is what it looks like:
I want the x-axis marks to show a dynamic version of Months, like:
My data structure either could show the "Date" as a string, or a TypeScript typeof Date object
data structure with date with a type of string
data structure with date with a type of Date
This is the data structure type:
The 'groupedAddRemove' is an array of this type
( AddRemoveBarChartType[] )
type AddRemoveBarChartType = {
createdDate: Date;
count: number;
type: "Add" | "Remove";
};
the "Type" can either be "Add" or "Remove". I had a boolean for this value previously, but the "Add" and "Remove" fit better to automatically have the legend say "Add" and "Remove". It could be changed back to a boolean if there is a better way to display it that way.
The data could be changed in other ways too, if that will simplify things. I am also open to using a D3.js implementation instead of Plot.plot.
I'm very new to Observable Plot.plot so any help is appreciated, thank you!
The problem I am facing is that in my web server I am sending a JSON as argument via render_template to my website where I want to use that JSON to show a google pie chart.
The problem is that if I assign the google pie chart data statically like this:
var data = new google.visualization.DataTable({
cols: [
{ id: "", label: "objeto", type: "string" },
{ id: "", label: "quantidade", type: "number" }
],
rows: [
{ c: [{ v: "Caixa 2" }, { v: 3 }] },
{ c: [{ v: "Caixa 3" }, { v: 3 }] },
{ c: [{ v: "Caixa 4" }, { v: 3 }] }
]
});
It works perfectly. On the other hand if I assign it dynamically with the JSON that I am receiving from my server like this:
var data = new google.visualization.DataTable({{json}});
It stops showing the google pie chart in my website.
The things I tried until now was litteraly adapting the JSON to the desired format by google charts because I thought that was the only problem, but now that it is in the required format and it works statically I do not know any way of assigning my received JSON to the data var.
This is my ideal function that I would like to work.
function drawChart() {
var data = new google.visualization.DataTable({{json}});
var options = {
title: 'gráfico Objeto/Quantidade',
is3D: true
};
var chart = new google.visualization.PieChart(
document.getElementById('piechart')
);
chart.draw(data, options);
}
Desired result:
http://prntscr.com/oejojv
Actual result:
http://prntscr.com/oejooe
The JSON string is being HTML-escaped. Assuming that you're using Flask (guessing based on your mention of render_template), you need to do something like {{json | safe}}.
Also, this assumes that you have total control over the content of this JSON, because you are otherwise susceptible to cross-site scripting attacks.
I'm beginner with webix, Just started to link with mongodb.
Now, I started loading my data from my DB.
But when it comes to deal with Objects, I can't get the data.
webix.ready(function () {
var grida = webix.ui({
container: "testA",
id: "pivot", url: "/rent", save: "rest->/rent",
view: "pivot",
height: 400,
width: 1000,
max: true,
structure: {
rows: ["from"],
columns: ["created"],
}
});
});
and this is my json field that I copied from my mongoDB.
"from" : {
"agency" : ObjectId("554"),
"place" : ObjectId("554dc4"),
"date" : ISODate("2014-08-09T06:00:00.000+0000"),
"completed" : false
},
First, how to access to the data inside the object?
Thanks for your help :)
You can use "scheme" to preprocess data before loading it in the pivot
webix.ui({
id: "pivot",
scheme:{
$init:function(obj){
obj.phone = obj.phones? obj.phones[0].number : "Empty"
}
}
I am developing from the c3.js using reusable charts in d3.js,but unable to get the data from the array of objects,i tried for the given format of the code.
var chart=c3.generate({
data:{
json:[
{"key":[2000],"value":100},{"key":[2001],"value":200},{"key":[2003],"value":300},{"key":[2004],"value":400},{"key":[2005],"value":500},{"key":[2006],"value":600},{"key":[2007],"value":700}
],
keys:{x:'key[0]',
value:'value',
}
},
axis: {
x: {
type: "category"
}
}
})
chart.data('value')[0].values[0].value
c3 documentation here
check out this fiddle
I believe this what you are going for:
var chart = c3.generate({
data:{
json:[
{"key":2000,"value":100},{"key":2001,"value":200},
{"key":2003,"value":300},{"key":2004,"value":400},
{"key":2005,"value":500},{"key":2006,"value":600},
{"key":2007,"value":700}
],
keys:{
x: "key",
value:['value']
}
},
axis: {
x: {
type: "category"
}
}
});
I'm not sure why you would have the key for a data point be an array (perhaps you want to swap the keys and values?), but here is a basic key, value line graph, which is what I think you are going for.
checkout out this fiddle adapted from Sikandar Tamboli's answer
I am trying to load the Flexigrid by using a JSON String which is returned by a WCF Service.
My Service has a public string GetContacts(string CustomerID) method and it returns a Json string.
That JSON string is created from a List object by using
System.Web.Script.Serialization.JavaScriptSerializer class. So, my aim is to bind the JSON string to the my Flexigrid as objects. I convert the web service result to objects using
var customer = eval("("+result+")");
The result is the JSON string being returned from service. Is there any way to bind customer objects to Flexigrid?
Flexigrid requires a format as follows in json
EDIT Thanks to EAMann for the format update.
total: (no of rec)
page : (page no)
rows : [{cell: [ (col1 value) , (col2 value) ,.. ] },
{cell: [ (col1 value) , (col2 value) ,.. ] }]
in order to bind the data to the grid i prefer sending the data across the wire and then formatting it on the client, but thats just me heres an example
function formatCustomerResults(Customers) {
var rows = Array();
for (i = 0; i < Customers.length; i++) {
var item = Customers[i];
//Do something here with the link
var link = "alert('opening item " + item.DealGuid + "');"
rows.push({
cell: [item.DealId,
item.Created,
item.CurrentStatus,
item.LastNote,
'<a href="javascript:void(0);" onclick="' + link + '" >view</a>'
]
});
}
return {
total: Customers.length,
page: 1,
rows: rows
};
}
and then all you need is
$("#FlexTable").flexAddData(formatCustomerResults(eval(data)));
ps this last bit is jquery syntax
almog.ori's answer is almost perfect. In fact, that's just about how I had built things before trying to Google the solution. One exception, though.
The JSON object should be:
total: (no of rec),
page : (page no),
rows : [{cell: [ (col1 value) , (col2 value) ,.. ] },
{cell: [ (col1 value) , (col2 value) ,.. ] }]
If you neglect the array format of the rows element, you'll end up choking Flexigrid and throwing all sorts of errors. But I've verified that this works flawlessly as long as you remember which parts of the script take JSON objects and which parts take arrays of JSON objects.
This is an older post but I thought I would add another way to use the excellent script provided by almog.ori.
The OP said that his data was being returned from a WCF service. If you mark the operation contract body style as bare you can use the preProcess property to add your formatCustomerResults (or other function) function to initially load the grid.
Like this:
$("#gridContainer").flexigrid({
url: '/YourService.svc/..',
method: 'GET',
dataType: 'json',
preProcess: formatCustomerResults,
...
});
function formatCustomerResults(data){
...
Hope this helps someone.
Make sure also that you are using the correct HTTP method, default is POST
To use GET:
$("#gridContainer").flexigrid({
url: '/json/files.json',
method: 'GET',
dataType: 'json',
...
preProcess solution by nameEqualsPNamePrubeGoldberg works perfect.
This is how my custom function for preProcess looks like.
var rows = Array();
$.each(data.rows,function(i,row){
rows.push({id:row.val1, cell:[row.val2,row.val3]});
});
return {
total:data.total,
page:data.page,
rows:rows
};
I recommend you to follow this sample to parse your JSON code and make requests to server:
Step 1: Parse using a function
function parsedForm(json)
{
var h = "";
if (json.post.val1)
h += "<b>Value 1</b>: " + json.post.val1 + "<br />";
h += "<b>Value 2</b>: " + json.post.val2 + "<br />";
h += "<b>Value 3</b>: " + json.post.val3 + "<br />";
if (json.post.val4)
h += "<b>Value 4</b>: " + json.post.val4 + "<br />";
$('#fdata').empty().html(h);
$('.formdata').slideDown();
return json;
}
Step 2: The flexigrid view code
$("#flex1").flexigrid({
url: 'post2.php',
dataType: 'json',
colModel : [
{display: 'ISO', name : 'iso', width : 40, sortable : true, align: 'center'},
{display: 'Name', name : 'name', width : 180, sortable : true, align: 'left'},
{display: 'Printable Name', name : 'printable_name', width : 120, sortable : true, align: 'left'},
{display: 'ISO3', name : 'iso3', width : 130, sortable : true, align: 'left', hide: true},
{display: 'Number Code', name : 'numcode', width : 80, sortable : true, align: 'right'}
],
searchitems : [
{display: 'ISO', name : 'iso'},
{display: 'Name', name : 'name', isdefault: true}
],
sortname: "iso",
sortorder: "asc",
usepager: true,
title: 'Countries',
useRp: true,
rp: 15,
showTableToggleBtn: true,
width: 700,
onSubmit: addFormData,
preProcess: parsedForm,
height: 200
});
Step 3: Additonally, you can validate or serialize the data to request server
function addFormData(){
//passing a form object to serializeArray will get the valid data from all the objects, but, if the you pass a non-form object, you have to specify the input elements that the data will come from
var dt = $('#sform').serializeArray();
$("#flex1").flexOptions({params: dt});
return true;
}
$('#sform').submit(function (){
$('#flex1').flexOptions({newp: 1}).flexReload();
return false;
});
I hope it will help!
Make sure you have the dataType option set to json.
$('#gridContainer').flexigrid({
singleSelect: true,
showToggleBtn: false,
dataType: 'json'
});
I believe the latest flex code broke the solution using preProcess.
addData: function (data) { //parse data
if (p.dataType == 'json') {
data = $.extend({rows: [], page: 0, total: 0}, data);
}
if (p.preProcess) {
data = p.preProcess(data);
}
You need to flip it so that the preProcess if comes before the type JSON if. Otherwise the function listed as an answer does not work properly.
It's old, I know... But here is an example of json that works:
{
"total": 5,
"page": "1",
"rows": [
{"cell": [1, "asd", "dsa", "2013-07-30"]},
{"cell": [2, "asd", "dsa", "2013-07-30"]},
{"cell": [3, "asd", "dsa", "2013-07-30"]},
{"cell": [4, "asd", "dsa", "2013-07-30"]},
{"cell": [5, "asd", "dsa", "2013-07-30"]}
]
}
(5 results in total; first page (they are NOT zero-based); 5 lines of data, each containing { ID, "asd", "dsa", "a date" } )
Try to make total your first element in you JSON string like this.
`{"total" : 2,"page":1,"rows":[ {"cell" : ["226 CLAVEN LN", "312"]},{"cell" : ["1377 FAIRFAX PIKE","280"]}]}`