I have JSON data source with nested obvar
jsonData = {
"block":[
{"name": "Block 1. Social Work",
"subblock": [{
"name": "Block 1.1. Student Org (SO)",
"paragraph": [
{
"name": "Head of SO",
"score": "10,00"
}, {
"name": "Head of Group" ,
"score": "9, 00 "
}]
}]
}]
};
Wher block.name = table caption, subblock.name =
var subbl_content=document.createElement("th");
subbl_content.colSpan=4;
subbl_content.innerHTML=jsonData[0].block[0].subblock[0].name;
paragraph = table content. I try to place it to DataTable in the following way
$(document).ready(function() {
.....
$('#example').DataTable(
{
data: jsonData,
columns: [
{ data: 'block[0].subblock[0].paragraph[0].name' },
{ data: 'block[0].subblock[0].paragraph[0].score' }
]
});
}) ;
It would seem that must work but as a result i have in one Cell next value Head of SOiHead of Group. But when i some change data like
$('#example').DataTable(
{
data: jsonData.block[0].subblock[0].paragraph,
columns: [
{ data: 'name' },
{ data: 'score' }
]
});
All works. Is it normal or are there other methods of solution?
Related
I have a simple dojo treeGrid that is categorized just by first column. But how to make it categorized/collapsible by second as well? Note the treeGrid has totals shown in each category. Also, is there a way to move totals to the category level but not to the bottom?
var layout = [
{ cells: [
[ {field: "year", name: "Year"},
{field: "childItems",
children: [ { field: "unid", name: "unid", hidden: true},
{ field: "geography", name: "Geography"},
{ field: "country", name: "Coungtry"},
{ field: "status", name: "Status"},
{ field: "credit", name: "Credit"},
{ field: "debit", name: "Debit"}
],
aggregate: "sum"
}
]] } ]
var jsonStore = new dojo.data.ItemFileWriteStore({ url: <...............>});
var grid = new dojox.grid.TreeGrid({
structure: layout,
store: jsonStore,
query: {type: 'year'},
queryOptions: {deep: true},
rowSelector: true,
openAtLevels: [false],
autoWidth: true,
autoHeight: true
},
dojo.byId("treeGrid"));
grid.startup();
dojo.connect(window, "onresize", grid, "resize");
sample JSON store:
{
"identifier": "id",
"label": "name",
"items": [
{
"id": "2018",
"type": "year",
"year": "2018",
"childItems": [
{
"id": "id0",
"geography": "Asia Pacific",
"country": "Australia",
"programname": "Program 1",
"totalPlanned": 0,
"totalForecasted": 0
},
{
.....
}
]
},
{
.....
}
]
}
You can find completely working example over here:
Now, let me try to explain it:
Data
First of all to support multiple levels in the grid you must have your data in the same format. For tree with n levels, you need to have n-1 level grouping in your data itself.
For example, JSON object below have 2 levels of grouping (year, geography) to support tree with 3 levels (root, parent, and child).
{
"identifier":"id",
"label":"name",
"items":[
{
"id":"2018",
"type":"year",
"year":"2018",
"geography":[
{
"id":"id1",
"geography":"Asia Pacific",
"childItems":[
{
"id":"ci1",
"country":"Australia",
"programname":"Program 1",
"credit":100,
"debit":50
}
]
}
]
}
]
}
Layout
To render a tree with n-levels you have to make sure layout of the tree is properly configured with same nesting as your data. To support data structure from JSON object above you need to set layout to:
[
{
cells:
[
[
{ field:"year", name:"Year" },
{
field:"geography",
children:
[
{ field:"geography", name:"Geography" },
{
field:"childItems",
children:[
{ field:"unid", name:"unid", hidden:true },
{ field:"country", name:"Country" },
{ field:"programname", name:"Program" },
{ field:"credit", name:"Credit" },
{ field:"debit", name:"Debit" }
],
aggregate:"sum",
},
]
}
]
]
}
]
You can see that, for each child level(s) you have to add a group (as I would like to call it) field and set first field within that group to your actual group field.
I hope this example will clear your doubt.
PS: In the jsfiddle version I have used formatters just to hide aggregate values for string fields.
I need to get a row from another array into my datatable
$(document).ready(function() {
$('#example').DataTable( {
"data": ex1,ex2,
"destroy": true,
columns: [
{ ex1: "Name" },
{ ex1: "Position" },
{ ex1: "Office" },
{ ex1: "Extn." },
{ ex1: "Start date" },
{ ex1: "Salary" },
{ ex2: "article_id" }
]
});
}
I should be able to connect the databases using "article_id" since they both have it and the values are the same, but how do I use it in a datatable?
if ex1[0]['article_id'] === ex2[0]['article_id'] --
put ex2[0]['article_id'] into datatable.
I need to create a multi leveled that is dynamic because I have to drill down to hundreds or even thousands of data providers that will load from the database. The flow goes like this: I have 1, 2, 3, 4, and 5 years that will drill down to 16 Departments each and will drill down to Courses 10 or more courses. Doing it manually is tedious and I need it to be dynamic. Please help me.
The variables:
var ccs_final_data = AmCharts.loadJSON("<?php echo base_url();?>index.php/osa/final_ccs_data");
//VAR CCS AVERAGE_FINAL
var drill_down_to_ccs_courses_average_final = AmCharts.loadJSON("<?php echo base_url();?>index.php/osa/ccs_courses_data_average_final");
var drill_down_to_ccs_sections_BSIT_average_final = AmCharts.loadJSON("<?php echo base_url();?>index.php/osa/ccs_sections_data_BSIT_average_final");
var drill_down_to_ccs_sections_ACT_average_final = AmCharts.loadJSON("<?php echo base_url();?>index.php/osa/ccs_sections_data_ACT_average_final");
var drill_down_to_ccs_sections_BSCS_average_final = AmCharts.loadJSON("<?php echo base_url();?>index.php/osa/ccs_sections_data_BSCS_average_final");
The graph:
var chart2 = AmCharts.makeChart( "ccs2", {
"theme": "light",
type: "serial",
pathToImages: "http://cdn.amcharts.com/lib/3/images/",
dataProvider: ccs_final_data,
categoryField: "category",
categoryAxis: {
labelRotation: 0,
gridPosition: "start"
},
valueAxes: [ {
title: "CCS FINAL TERM - Passing"
} ],
graphs: [ {
valueField: "value",
colorField: "color",
type: "column",
lineAlpha: 100,
fillAlphas: 1
} ],
chartScrollbar: {
"updateOnReleaseOnly": true
},
chartCursor: {
bulletsEnabled: "enabled",
bulletSize: 15,
cursorAlpha: 100,
cursorColor: "#CC0000",
zoomable: true,
categoryBalloonEnabled: true
},
export: {
enabled: true
}
} );
Here's the drill down stuff:
chart2.addListener("clickGraphItem", function (event) {
if(event.item.category == "Average"){
event.chart.dataProvider = drill_down_to_ccs_courses_average_final;
event.chart.validateData();
chart2.addListener("clickGraphItem", function (event) {
if(event.item.category == "BSIT"){
event.chart.dataProvider = drill_down_to_ccs_sections_BSIT_average_final;
event.chart.validateData();
}
else if(event.item.category == "ACT"){
event.chart.dataProvider = drill_down_to_ccs_sections_ACT_average_final;
event.chart.validateData();
}
else if(event.item.category == "BSCS"){
event.chart.dataProvider = drill_down_to_ccs_sections_BSCS_average_final;
event.chart.validateData();
}
});
}
I'd say the best way to make it dynamic is to include some custom field for each data point in your data that would be passed in to server-side script so it knows which data to load.
I'm assuming your data looks like this now:
[ {
"category": "BSIT",
"value": 100
}, {
"category": "ACT",
"value": 200
}, {
"category": "BSCS",
"value": 150
} ]
You could easily add a third field to hold the information for drill-down data load:
[ {
"category": "BSIT",
"value": 100,
"drill": "ccs_sections_data_BSIT_average_final"
}, {
"category": "ACT",
"value": 200,
"drill": "ccs_sections_data_ACT_average_final"
}, {
"category": "BSCS",
"value": 150,
"drill": "ccs_sections_data_BSCS_average_final"
} ]
Then, when clickGraphItem event occurs, you could just take that info and pass it to load script dynamically:
chart2.addListener( "clickGraphItem", function( event ) {
if ( event.item.dataContext.drill !== undefined ) {
event.chart.dataProvider = AmCharts.loadJSON( "<?php echo base_url();?>index.php/osa/" + event.item.dataContext.drill );
event.chart.validateData();
}
} );
This way, you could have any number of drill-down levels, with each level data containing info about where to look for the data for the next level.
Also, I'm not sure as you haven't posted the code for it, so I'm assuming that AmCharts.loadJSON method is synchronous. If it's not (for example if you are using method from Data Loader), you will need to assign the chart's dataProvider after the data is loaded.
I am trying to filter results using Typeahead.js. I can currently filter the results using a field called activity_title. This works fine.
How can I filter my results by a second value? In this case, I would like to select only the results that have a certain value for activity_level. I need to set this when the typeahead is initialised rather than hard coding it into the Bloodhound initialisation (e.g. I don't want to use url: 'api/activity/&range=1,3')
I have the following valid JSON that I access remotely:
{
"meta": [
{
"name": "activity_id",
"table": "table",
"max_length": 4
},
{
"name": "activity_title",
"table": "table",
"max_length": 91
},
{
"name": "activity_level",
"table": "table",
"max_length": 2
}
],
"detail": [
{
"activity_id": "57",
"activity_title": "Help old ladies to cross the road.",
"activity_level": "2"
},
{
"activity_id": "58",
"activity_title": "Help mum with the washing up.",
"activity_level": "3"
},
{
"activity_id": "59",
"activity_title": "Shine my shoes",
"activity_level": "1"
},
{
"activity_id": "60",
"activity_title": "Put the bins out",
"activity_level": "1"
}
]
}
I set up a Bloodhound instance like this:
var activities = new Bloodhound({
datumTokenizer: function (datum) {
return Bloodhound.tokenizers.whitespace(datum.activity_title);
},
queryTokenizer: Bloodhound.tokenizers.whitespace,
prefetch: {
url: '/api/activity/',
filter: function(data) {
return $.map(data['detail'], function(detail) {
return {
activity_id: detail.activity_id,
activity_title: detail.activity_title,
objective_level: detail.objective_level
};
});
}
}
});
I use Typeahead.js to do a lookup on the data as I type.
$( document ).on( "focus", ".typeahead-init", function() {
// + '&range=' + minimum + ',' + maximum
var minimum = $('#group-level-min-1').val();
var maximum = $('#group-level-max-1').val();
$(this).typeahead({
highlight: true
},
{
name: 'activity_title',
displayKey: 'activity',
source: activities.ttAdapter(),
templates: {
header: '<div class="header-name">Activities</div>',
empty: [
'<div class="empty-message">',
'No activities match your search',
'</div>'
].join('\n'),
suggestion: Handlebars.compile('<div class="typeahead-activity" id="typeahead-activity-{{activity_id}}"><strong>{{objective_level}}</strong> - {{activity_title}}</div>')
}
})
//info on binding selection at https://github.com/twitter/typeahead.js/issues/300
.bind('typeahead:selected', function(obj, datum, name) {
var target = $(this).closest('.activity-container');
var activityId = datum['activity_id'];
var url = '/api/activity/id/'+activityId;
$(target).children('.activity-id').val(activityId);
//http://runnable.com/UllA9u8MD5wiAACj/how-to-combine-json-with-handlebars-js-for-javascript-ajax-and-jquery
var raw_template = $('#activity-output').html();
// Compile that into an handlebars template
var template = Handlebars.compile(raw_template);
// Fetch all data from server in JSON
$.get(url,function(data,status,xhr){
$.each(data,function(index,element){
// Generate the HTML for each post
var html = template(element);
// Render the posts into the page
target.append(html);
});
});
});
$(this).removeClass("typeahead-init");
$(this).focus();
});
This has been cobbled together from several answers on Stackoverflow and others. Any help greatly appreciated.
I've just started to learn about Mustache, but I don't understand how can I do this:
I have this JSON object :
var columnsDefinition = {
"columns": [
{
"header": 'First name',
"values": ['John', 'Jack', 'Abe', 'Adelle', 'Jim', 'Andrew', 'Matthew'],
"type": 'text'
},
{
"header": 'Last name',
"values": ['Carpenter', 'Reaper', 'Lincoln', 'Aidan', 'Raynor', 'Doe'],
"type": 'text'
},
{
"header": 'Profession',
"values": ['butcher', 'doctor', 'farmer', '', 'pilot', 'singer', ''],
"type": 'select'
},
{
"header": 'Employed',
"values": [true, false, true, true, false],
"type": 'checkbox'
}
],
"search": true
};
I want to create this :
This is what I've tried, but I don't know how to put values on each column, not on each row.
this.testDiv = $("#testDiv");
this.header = "{{#columns}}<th>{{header}}</th>{{/columns}}";
this.body = "{{#columns}}<tr>{{#values}}<td>{{.}}</td><{{/values}}/tr>{{/columns}}";
this.html = Mustache.to_html(this.header, this.columnsDefinition);
this.html2 = Mustache.to_html(this.body, this.columnsDefinition);
$("#testDiv table thead tr").append(this.html);
$("#testDiv table tbody").append(this.html2);
How can I create the table above? Thank you.
I don't believe this can be done out of the box.
If you can't modify the JSON object that you currently have, you're better off generating another JSON object that will pivot the data and feed that one to Mustache.