At this code javascrip give an error
$.each(JSON, function(i, array) {
chart.series[i].name = array.teamName;
chart.series[i].setData(array.teamPower, true);
});
I must define the chart.series[i] because it say "Cannot set property 'name' of undefined"
but i can't find a way in order to do this.
Because it fonction runs with requestData so it came after chart determine with options
function showGraph() {
chart = new Highcharts.Chart(option);
}
chart: {
renderTo: 'graphicShow',
type: 'spline',
events: {
load: requestData
}
}
...in option...
title: {
text: 'Power %'
},
series: []
...
You need to looka at the "Methods and Properties" part of the API. See http://api.highcharts.com/highcharts#Chart (There is an jsFiddle on the documentation page as well).
var chart = new Highcharts.Chart(options);
chart.addSeries({
name: array.teamName,
data: array.teamPowher
});
If you are going to add several series you should set the redraw flag to false and then call redraw manually after as that will be much faster.
var chart = new Highcharts.Chart(options);
chart.addSeries({
name: array.teamName,
data: array.teamPower
}, false);
chart.addSeries({
name: array.teamName,
data: array.teamPower
}, false);
chart.redraw();
You too can specify as second option of addSeries a boolean value, that indicates if it redraws or not
Related
I would like to know if the following approach is supported:
Define grid schema and columns and initialize with an empty array:
var dataSource = new kendo.data.DataSource({
data: [] // intentionally empty!
});
$("#grid").kendoGrid({
dataSource: dataSource,
schema: {
model: {
fields: {
arrive: {type: "number"},
depart: {type: "number"},
src: {type: "string"}
}
}
},
columns: [
{ field: "arrive", groupable: false, title: "arrive",width:88},
{ field: "depart", groupable: false, title: "depart",width:88},
{ field: "src", groupable: true, title: "src", width:44 }
]
etcetera
});
Then, after configuration/initialization, bind to the Change event:
var grid = $('#grid').data('kendoGrid');
grid.dataSource.bind("change", function (e) {
dataChanged();
});
function dataChanged() {
var grid = $("#grid").data("kendoGrid");
grid.refresh();
}
Then do this:
function populateDatasource(event, data) {
var grid = $('#grid').data('kendoGrid');
var parsedData = $.parseJSON(data);
grid.dataSource.data(parsedData);
}
which would trigger the changed event and refresh the grid. I am thinking that the observe pattern might have some trouble if the dataSource is initialized with an empty array.
I am not sure what you mean by observe pattern. But the grid can have an empty data source. Here is a demo: http://jsbin.com/izizut/1/edit
Your grid configuration is wrong. The schema setting is part of the data source configuration not the grid. You can find more information in the data source API reference.
Also there is no need to subscribe to the change event of the data source in this case. The grid is listening to it by default and will get refreshed automatically.
I have a working sort-able grid using the ext 3.4 grid filter plugin. I would like to default the active column to filter true values. User who needs the inactive records could remove the filter. How do I specify a default filter column and value?
Thanks in advance!
colModel: new Ext.grid.ColumnModel({
defaults: {
sortable: true
// How do I specify a default filter value
//
// Only show active records unless the user changes the filter...
},
columns: [{
dataIndex:'f_uid',
id:'f_uid',
header:'ID',
hidden:true
}, {
dataIndex:'f_name',
id:'f_name',
header:'Name',
}, {
xtype:'booleancolumn',
dataIndex:'f_active',
id:'f_active',
header:'Active',
filterable:true,
trueText:'Active',
falseText:'Inactive'
}]
I realise this is an old question but it took me a while to find a solution, therefore I thought I would share.
1) The filter can be set using the value property in the filter.
filter: {
type: 'LIST',
value: ['VALUE TO FILTER']
}
2) In order to initially filter the data use the filterBy() method in the store. This could be defined in the onRender event handler.
this.getStore().load({
scope:this,
callback: function() {
// filter the store
this.getStore().filterBy(function(record, id) {
// true will display the record, false will not
return record.data.DATA_TO_FILTER == 'VALUE TO FILTER ';
});
}
});
The answer was in the Filter.js source code. The filter object within the column definition can be used to configure the default behavior.
}, {
xtype:'booleancolumn',
dataIndex:'f_active',
id:'f_active',
header:'Active',
trueText:'Active',
falseText:'Inactive',
filterable:true,
filter: {
value:1, // 0 is false, 1 is true
active:true // turn on the filter
}
}
I have encountered the same problem and I found that #John's answer is right, I can make it work with the sample http://dev.sencha.com/deploy/ext-4.0.0/examples/grid-filtering/grid-filter-local.html, for the grid-filter-local.js, just add the code like:
grid.getStore().load({
scope:this,
callback: function() {
// filter the store
grid.getStore().filterBy(function(record, id) {
// true will display the record, false will not
return record.data.size === 'small';
});
}
});
before the original code store.load(), and wipe off the store.load().
Then it will only show the record with size equals 'small' at the first load of the web page. Cheers!
I've made a universal helper class that allows you to set any default values in column definition.
https://gist.github.com/Eccenux/ea7332159d5c54823ad7
This should work with both remote and static stores. Note that this also works with filterbar plugin.
So your column item is something like:
{
header: 'Filename',
dataIndex: 'fileName',
filter: {
type: 'string',
// filename that starts with current year
value: Ext.Date.format(new Date(), 'Y'),
active:true
}
},
And then in your window component you just add something like:
initComponent: function() {
this.callParent();
// apply default filters from grid to store
var grid = this.down('grid');
var defaultFilters = Ext.create('Ext.ux.grid.DefaultFilters');
defaultFilters.apply(grid);
},
Using Ext.ux.grid.FiltersFeature, I have remote filters and I am trying to write a function to apply a date filter on a grid column programmatically (rather than clicking on the filter drop down menu in the column header). The first time I run the function the grid store gets reloaded without the filter. When I run the function a second time (and every time thereafter) it works totally fine, the store reloads with the filters. Here is the gist of the function I have:
// a filter object for testing
aFilter = {type: 'date', field: 'a_date_field', comparison: 'gt', value: '2012-03-08 00:00:00'}
var grid = Ext.create('Ext.grid.Panel', {
store: store,
features: [{
ftype: 'filters',
}],
columns[{
header: 'ID',
dataIndex: 'id',
itemId: 'id',
width: 40,
}, {
xtype: 'datecolumn',
header: 'Date',
dataIndex: 'a_date_field',
itemId: 'a_date_field',
width: 75,
format:'j-M-Y',
filterable: true
}],
listeners: {
'afterrender': function() {
// Need to create the filters as soon as the grid renders
// rather than waiting for the user to click on the header
grid.filters.createFilters();
}
},
bbar: [{
text: 'Do a filter',
handler: function() {
// get the filter that is attached to the grid
var gridFilter = grid.filters.getFilter(aFilter.field);
// have to do this to create a menu for this filter
gridFilter.init({dataIndex: aFilter.field, type: aFilter.type, active: true});
// if this column is a date filter column
if (gridFilter.type == 'date') {
var dateValue = Ext.Date.parse(aFilter.value, 'Y-m-d H:i:s');
if (filter.comparison == 'gt') {
gridFilter.setValue({after: dateValue});
} else {
gridFilter.setValue({before: dateValue});
}
}
}
}
});
I also found that this function works the first time if I click on any grid header menu before I run the function.
I've been trying to find out what changes are made to the grid which make the filter work after the first attempt fails or what clicking on any grid header does to make it work. But nothing I add seems to fix it so it will run the first time. Has anyone implemented this successfully?
I have workaround:
bbar: [{
text: 'Do a filter',
handler: function() {
var grid = this.up('grid');
var dateValue = Ext.Date.parse(aFilter.value, 'Y-m-d H:i:s');
var value = aFilter.comparison == 'gt' ? {after: dateValue} : {before: dateValue};
var gridFilter = grid.filters.getFilter(aFilter.field);
if (!gridFilter) {
gridFilter = grid.filters.addFilter({
active: true,
type: aFilter.type,
dataIndex: aFilter.dataIndex,
});
gridFilter.menu.show();
gridFilter.setValue(value);
gridFilter.menu.hide();
} else {
gridFilter.setActive(true);
}
Ext.Function.defer(function(){
gridFilter = grid.filters.getFilter(aFilter.field);
gridFilter.setValue(value);
}, 10);
}
}]
As you can see I actually apply filter 2 times.
As an update, I expanded this function and modified it to work with ExtJS 4.1.1
Here is an example of the function to set grid filters dynamically (without the user needing to click on the menu items). Afterwards, the filtered items will be visible to the user in the grid column header menus as if he clicked on them and set them manually.
The "grid" argument is a grid with FiltersFeature that you want to filter. The other argument is an array of "filter" objects (I'll show an example below), the function simply applies all the passed "filter" objects to the grid.
doGridFilter: function(grid, filters) {
// for each filter object in the array
Ext.each(filters, function(filter) {
var gridFilter = grid.filters.getFilter(filter.field);
gridFilter.setActive(true);
switch(filter.data.type) {
case 'date':
var dateValue = Ext.Date.parse(filter.data.value, 'm/d/Y'),
value;
switch (filter.data.comparison) {
case 'gt' :
value = {after: dateValue};
break;
case 'lt' :
value = {before: dateValue};
break;
case 'eq' :
value = {on: dateValue};
break;
}
gridFilter = log.filters.getFilter(filter.field);
gridFilter.setValue(value);
gridFilter.setActive(true);
break;
case 'numeric':
var value;
switch (filter.data.comparison) {
case 'gt' :
value = {gt: filter.data.value};
break;
case 'lt' :
value = {lt: filter.data.value};
break;
case 'eq' :
value = {eq: filter.data.value};
break;
}
gridFilter = log.filters.getFilter(filter.field);
gridFilter.setValue(value);
gridFilter.setActive(true);
break;
case 'list':
gridFilter = log.filters.getFilter(filter.field);
gridFilter.menu.setSelected(gridFilter.menu.selected, false);
gridFilter.menu.setSelected(filter.data.value.split(','), true);
break;
default :
gridFilter = log.filters.getFilter(filter.field);
gridFilter.setValue(filter.data.value);
break;
}
});
}
Here's an example of a "filter" object array.
// an example of a "filters" argument
[{
field: 'some_list_column_data_index',
data: {
type: 'list',
value: 'item1,item2,item3,item4,item5,item6,item7'
}
}, {
field: 'some_date_column_data_index',
data: {
type: 'date',
comparison: 'gt',
value: '07/07/2007'
}
}]
One caveat, you need to "create" the filters manually before using this function. Normally FiltersFeature grid filters are "created" the first time a user clicks on one of them, that may not happen if the user just wants to apply one of these predefined filters.
That can be handled easily by including this afterrender listener in the gridpanel.
listeners: {
// must create the filters after grid is rendered
afterrender: function(grid) {
grid.filters.createFilters();
}
}
Just add
filter: true
to grid columns description like this:
me.columns = [
{header:"Name", dataIndex:"name", editor:"textfield", filter: true},
];
if you want to get the filter work after the first attempt, first instance create.
Here is something that may be worth looking into. It seems that the filters plugin is listening for menucreate event to initialize the filters. I wonder if menu create event is deferred until necessary and hence the filters don't get initialized?
/**
* #private Handle creation of the grid's header menu. Initializes the filters and listens
* for the menu being shown.
*/
onMenuCreate: function(headerCt, menu) {
var me = this;
me.createFilters(); //<------
menu.on('beforeshow', me.onMenuBeforeShow, me);
},
Do you want to apply grid filter or may be store.filter() capability would suit you better? In this case just filter the store, and grid will display filtered records.
I discovered another way to implement this. It appears that grid features are only bound to the grid after the grid is rendered. This means that any setup of the filter will not take effect until after the grid is rendered. The initial load of the store appears to be initiated before the grid is rendered.
I solved my problem by creating my store with a memory proxy containing no data.
me.store = Ext.create('Ext.data.Store', {
model: 'SummaryData',
data: [],
proxy: {
type: 'memory',
reader: 'array'
},
remoteSort: true,
remoteFilter: true
});
Then set up an afterrender handler on the grid to poke in the correct proxy and initiate a load of the store.
afterrender: function () {
var me = this;
me.store.setProxy({
type: 'ajax',
url : '/print_unallocated/change_site__data',
reader: {
type: 'json',
root: 'rows'
},
listeners: {
exception: function (proxy, response) {
Max.reportException(response);
}
}
});
me.filters.createFilters();
me.store.load();
},
In the source, you can see a comment related to this.
// Call getMenu() to ensure the menu is created, and so, also are the filters. We cannot call
// createFilters() withouth having a menu because it will cause in a recursion to applyState()
// that ends up to clear all the filter values. This is likely to happen when we reorder a column
// and then add a new filter before the menu is recreated.
me.view.headerCt.getMenu();
You can test whether the menu has been created before applying your filter. If it hasn't, do it yourself.
if(!grid.getView().headerCt.menu){
grid.getView().headerCt.getMenu();
}
I asked this question in the Ext JS forums, but I received no responses, so I am asking here.
I have a TreePanel (code below) that uses a TreeLoader and an AsyncTreeNode. In my API method specified by the TreeLoader's dataUrl, I return a JSON array to populate the tree.
This works great, of course. However, I need to return an additional item--an integer--in addition to the array, and I need to display that value somewhere else in my UI. Is this possible? If not, what else would be a good solution?
Here's the code I have currently:
tree = new Ext.tree.TreePanel({
enableDD: true,
rootVisible: false,
useArrows: true,
loader: new Ext.tree.TreeLoader({
dataUrl: '/api/method'
}),
root: new Ext.tree.AsyncTreeNode()
});
I want to return one single integer value for the entire response--not per node. Basically my API method will create a database record, and I need to return a value from that database record.
EDIT Thanks to Mike, I have solved this problem. I extended the Ext.tree.TreeLoader class like so:
TreeLoaderWithMetaData = Ext.extend(Ext.tree.TreeLoader, {
processResponse : function(response, node, callback) {
var json = response.responseText;
try {
var o = eval("("+json+")");
metaData = o.shift();
node.beginUpdate();
for(var i=0, len=o.length; i<len; i++) {
var n = this.createNode(o[i]);
if (n) {
node.appendChild(n);
}
}
node.endUpdate();
if(typeof callback == "function") {
callback(this, node);
}
}
catch (e) {
this.handleFailure(response);
}
}
});
And then I can reference variables in the meta data like public members: metaData.my_variable1, metaData.my_variable2. My AJAX data from the server just has an extra array item:
[{"my_variable1":"value1","my_variable2":"value2"},{"id":"node1","text":"Node 1",children:[{"id":"node1nodeA","text":"Node 1 Node A"}]]
You need to override the processResponse function in TreePanel and then you'll be able to return whatever format JSON you'd like:
From the ExtJS forums:
http://www.extjs.com/forum/showthread.php?32772-Passing-JSON-string-from-Grails-to-populate-TreePanel
The code at the bottom of that thread will help you.
As far as i understood, you want to pass additional parametrs with json and display it somewhere else when tree is loaded.
In this case you can simply return from server modified JSON like this
[{
id: 1,
yourParmam : 'val',
text: 'A leaf Node',
leaf: true
},{
id: 2,
yourParmam : 'val',
text: 'A folder Node',
children: [{
id: 3,
yourParmam : 'val',
text: 'A child Node',
leaf: true
}]
}]
Then subscribe to even load : ( Object This, Object node, Object response ) and simply parse response to find out you parm and do whatever you need
Am trying to set 'seriesstyles' to piechart dynamically from the JSON data. When the 'oneWeekStore' loads the JSON data, I wish to iterate through the 'color' of each record and setSeriesStyles dynamically to PieChart. Below is the snippet.
var oneWeekStore = new Ext.data.JsonStore({
id:'jsonStore',
fields: ['appCount','appName'],
autoLoad: true,
root: 'rows',
proxy:storeProxy,
baseParams:{
'interval':'oneWeek',
'fromDate':frmDt.getValue()
},
listeners: {load: {
fn:function(store,records,options) {
/*I wish iterate through each record,fetch 'color'
and setSeriesStyles. I tried passing sample arrays
as paramater to setSeriesStyles like
**colors= new Array('0x08E3FE','0x448991','0x054D56');
Ext.getCmp('test12').setSeriesStyles(colors)**
But FF throws error "this.swf is undefined". Could
you please let me know the right format to pass as
parameter. */
}
});
var panel = new Ext.Panel{
id: '1week', title:'1 week',
items : [
{ id:'test12',
xtype : 'piechart',
store : oneWeekStore,
dataField : 'appCount',
categoryField : 'appName',
extraStyle : {
legend:{
display : 'right',
padding : 5,
spacing: 2, font :color:0x000000,family:
'Arial', size:9},
border:{size :1,color :0x999999},
background:{color: 0xd6e1cc}
} } } ] }
My JSON data looks below:
{"success":true,"rows":[{"appCount":"9693814","appName":"GED","color":"0xFB5D0D"},{"appCount":"5731","appName":"SGEF"","color":"0xFFFF6B"}]}
Your guidance is highly appreciated
You have a classic race condition there - your setting an event in motion that relies on a Component who's status is unknown.
The event your setting off is the loading of the data Store, when that has finished loading it is trying to interact with the Panel, but at that point we don't know if the Panel has been rendered yet.
Your best bet is to make one of those things happen in reaction to the other, for example:
1 ) load the store
2 ) on load event fired, create the panel
var oneWeekStore = new Ext.data.JsonStore({
id:'jsonStore',
...,
listeners: {
load:function(store,records,options) {
var panel = new Ext.Panel({
...,
seriesStyles: colors,
...
});
}
}
});
or
1 ) create the panel (chart)
2 ) on render event of the panel, load the store (remove autoLoad:true)
var panel = new Ext.Panel({
id: '1week',
...,
listeners: {
render: function(pnl){
oneWeekStore.load();
}
}
});
Hope that helps.