create a dynamic grid in extjs - dynamic

I need to create a dynamic gridpanel in ExtJS . I use an actioncolumn for this:
handler: function(view, rowIndex, colIndex, item, e) {
var tabs = Ext.getCmp('northPanel');
var rec = view.getStore().getAt(rowIndex);
modelFactory(rec.get('Reference'), rec.get('ResultFields'));
console.log(rec.get('ResultFields'));
console.log('start adding tab');
tabs.add({
title: 'Report: ' + rec.get('Reference'),
closable: true,
dockedItems: [{
xtype: 'toolbar',
dock: 'top',
items: [{
xtype: 'tbfill'
}, {
xtype: 'button',
text: 'Export report'
}, {
xtype: 'button',
text: 'Refresh data'
}]
}],
xtype: 'tabpanel',
items: [{
xtype: 'gridpanel',
title: 'Gridview',
forceFit: true,
store: ND.store,
columns: []
}]
});
console.log('tab created');
},
Now I need to create the columns for this grid. The columns I need to make are in the rec.get('ResultFields'). When I use the console.log() I see this in the firebug:
[Object {
name = "currentSimAllocationByCcu", type = "textfield", format = null
}, Object {
name = "wanNumber", type = "textfield", format = null
}, Object {
name = "carrierName", type = "textfield", format = null
}, Object {
name = "dataPackageName", type = "textfield", format = null
}, Object {
name = "simIccid", type = "textfield", format = null
}, Object {
name = "expiryTime", type = "textfield", format = null
}, Object {
name = "bytesRx", type = "textfield", format = null
}, Object {
name = "bytesTx", type = "textfield", format = null
}]
How can I create columns with this?

What seems to be a problem?
If you get information about columns before you create a grid - then create array or columns based on array of your fields. Something like this:
var _cols = [],
_flds = rec.get('ResultFields');
Ext.Array.each(_flds, function(f) {
_cols.push(Ext.create('Ext.grid.column.Column', {
text: f.get('name'),
dataIndex: f.get('name')
}));
});
And then just use that _cols when creating grid.

Related

How to display ScheduleState and Blocked columns in custom Grid the way Rally's grid does

I'm trying to create a custom Rally app that displays data in a grid view. In another question Rally SDK App Using Grid with collapsible tree of children stories, nickm posted some sample code
Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
launch: function() {
var today = new Date().toISOString();
Ext.create('Rally.data.wsapi.Store', {
model: 'UserStory',
fetch: ['ObjectID', 'FormattedID', 'Name', 'ScheduleState', 'Feature'],
autoLoad: true,
filters: [
{
property: 'Iteration.StartDate',
operator: '<=',
value: today
},
{
property: 'Iteration.EndDate',
operator: '>=',
value: today
},
{
property: 'Feature',
operator: '!=',
value: null
}
],
listeners: {
load: this._onDataLoaded,
scope: this
}
});
},
_onDataLoaded: function(store, records){
var that = this;
var promises = [];
_.each(records, function(story) {
promises.push(that._getFeature(story, that));
});
Deft.Promise.all(promises).then({
success: function(results) {
that._stories = results;
that._makeGrid();
}
});
},
_getFeature: function(story, scope) {
var deferred = Ext.create('Deft.Deferred');
var that = scope;
var featureOid = story.get('Feature').ObjectID;
Rally.data.ModelFactory.getModel({
type: 'PortfolioItem/Feature',
scope: this,
success: function(model, operation) {
fetch: ['State'],
model.load(featureOid, {
scope: this,
success: function(record, operation) {
var featureState = record.get('State')._refObjectName;
var storyRef = story.get('_ref');
var storyOid = story.get('ObjectID');
var storyFid = story.get('FormattedID');
var storyName = story.get('Name');
var storyState = story.get('ScheduleState');
var feature = story.get('Feature');
result = {
"_ref" : storyRef,
"ObjectID" : storyOid,
"FormattedID" : storyFid,
"Name" : storyName,
"ScheduleState" : storyState,
"Feature" : feature,
"FeatureState" : featureState,
"FeatureID" : featureOid
};
deferred.resolve(result);
}
});
}
});
return deferred;
},
_makeGrid: function() {
var that = this;
if (that._grid) {
that._grid.destroy();
}
var gridStore = Ext.create('Rally.data.custom.Store', {
data: that._stories,
groupField: 'FeatureID',
pageSize: 1000,
});
that._grid = Ext.create('Rally.ui.grid.Grid', {
itemId: 'storyGrid',
store: gridStore,
features: [{ftype:'grouping'}],
columnCfgs: [
{
text: 'Formatted ID', dataIndex: 'FormattedID', xtype: 'templatecolumn',
tpl: Ext.create('Rally.ui.renderer.template.FormattedIDTemplate')
},
{
text: 'Name', dataIndex: 'Name',
},
{
text: 'ScheduleState', dataIndex: 'ScheduleState',
},
{
text: 'Feature', dataIndex: 'Feature',
renderer: function(val, meta, record) {
return '' + record.get('Feature').FormattedID + '';
}
},
{
text: 'Feature State', dataIndex: 'FeatureState',
}
]
});
that.add(that._grid);
that._grid.reconfigure(gridStore);
}
});
I'd like to display the ScheduleState and Blocked columns the same way that the Rally Grid shows them (as graphic representations). I've tried to figure out how to use templatecolumn xtype by using the following in my columnCfgs block:
{ text: 'State', dataIndex: 'ScheduleState', xtype: 'templatecolumn',
tpl: Ext.create('Rally.ui.renderer.template.ScheduleStateTemplate') }
This fails and causes a JS error in the sdk-debug.js:
Uncaught TypeError: Cannot read property 'getAllowedValueStore' of
undefined sdk-debug.js:190539 Ext.define.loadStates
I get different errors with the Blocked column but I haven't been able to figure out how to get it to display as the red blocked icon.
With some tweaking I expect this to work in the next release of AppSDK2, but right now the rendering of the ScheduleState and Blocked will only work with wsapi data store. Using
tpl: Ext.create('Rally.ui.renderer.template.ScheduleStateTemplate')
is not sufficient. Custom store has no access to the valid states.
UPDATE
Rendering of ScheduleState and Blocked works in the current x version of AppSDK2 as of the date of this update, 5/22
<script type="text/javascript" src="/apps/x/sdk.js"></script>
This fix will eventually make its way to the next official release of AppSDK2 but for now you may use it with x version of AppSDK2.
Warning: x version of AppSDK is never stable - changes are made to it constantly.
See full code example here.
In x version of AppSDK you may do this:
{
text: 'ScheduleState', dataIndex: 'ScheduleState', xtype: 'templatecolumn',
tpl: Ext.create('Rally.ui.renderer.template.ScheduleStateTemplate',
{
states: ['Defined', 'In-Progress', 'Completed', 'Accepted'],
field: {name: 'ScheduleState' }
})
},
{
text: 'Blocked', dataIndex: 'Blocked', xtype: 'templatecolumn',
tpl: Ext.create('Rally.ui.renderer.template.BlockedTemplate')
}
Also, for now, set this to false in the grid config:
enableBlockedReasonPopover: false

How to add new childs dynamically from json to treenode in extjs4

i am working in extjs4. I have created treepanel view as-
Now on clicking on node surrounding,i am retrieving its id,sending it to server side and retriving its corresponding childs. I am getting this serverside output in json format as-
{"children":[{"text":"Subgeo1","leaf":true,"expanded":false,"checked":false},{"text":"Subgeo2","leaf":true,"expanded":false,"checked":false}]}
So now i want to insert this above json elements as childs of node "surrounding". So how to update tree store with this new childs? Or how can i add childs dynamically? please help me
Here's my example how I add elements on my tree:
on_AddTreeNodes: function (win) {
var _this = this;
//your tree
var tree = win.down('treepanel[name=main_tree]');
//get tree root
var root = tree.getRootNode();
var first = root.firstChild;
var _index = first.childNodes.length - 1;
//adding folder
first.insertChild(_index, { text: 'New folder name', leaf: false });
var data = first.getChildAt(_index);
Ext.Ajax.request({
url: 'your url',
method: 'GET',
params: {
//some params
},
success: function (objServerResponse) {
//if success, you add your data from server into your tree
data.insertChild(data.firstChild, {
text: 'your leaf name',
leaf: true,
//your other params
});
});
//sync your tree store
tree.getStore().sync();
}
In my example I use insertChild - this method adding childs in my tree.
Here's some information that should help you : work with tree in ExtJs
In my view I have
Ext.applyIf(me, {
items: [
{
xtype: 'treepanel',
name: 'main_tree',
title: 'Menu',
region: 'west',
collapsible: true,
rootVisible: false,
viewConfig: {
width: 230
},
store: Ext.create('Ext.data.TreeStore', {
root: {
expanded: true,
children: [
{
text: '',
expanded: true,
children: [
{ text: 'Menu item', leaf: true, param1: 'somedata', param2: 'somedata', param3: 'somedata' },...
and when I use:
data.insertChild(data.firstChild, {
text: 'your leaf name',
leaf: true,
//your other params
});
instead '//your other params' you get params from your JSON and write like this:
data.insertChild(data.firstChild, {
text: 'your leaf name',
leaf: true,
param1: 'jsondata',
param2: 'jsondata',
param3: 'jsondata'
});

Sencha Touch Grouper Property Conversion

I have a list reading from a Json store which contains a grouper on a field of type int. This field is called "req" in the sample model below. However, rather than group by the int value, I would like to assign a text value instead, so for example, in case of "1" I would group by "Yes" and in case of "0" I would group by "No". The conversion can be hard coded as it will not change. Where do I make this conversion in my code? Thanks for your help
Ext.define('MyApp.store.MyStore', {
extend: 'Ext.data.Store',
requires: [
'MyApp.model.MyData'
],
config: {
model: 'MyApp.model.MyData',
storeId: 'MyStore',
proxy: {
type: 'ajax',
url: '/path/to/data.json',
reader: {
type: 'json',
rootProperty: 'items'
}
},
grouper: {
property: 'req',
sortProperty: 'req'
},
groupDir: 'DESC'
}
});
Model:
Ext.define('Mypp.model.MyModel', {
extend: 'Ext.data.Model',
config: {
fields: [
{
name: 'example',
type: 'string'
},
{
name: 'req',
type: 'int'
}
]
}
});
Add to the Model a calculated field with convert() function:
Ext.define('Mypp.model.MyModel', {
extend: 'Ext.data.Model',
config: {
fields: [
{
name: 'example',
type: 'string'
},
{
name: 'req',
type: 'int'
},
{
name: 'reqDisplay',
type: 'string',
convert: function (value, record) {
if (value == null) {
var req = record.get('req');
value = req ? 'Yes' : 'No'
}
return value;
}
}
]
}
});
... and use it instead
grouper: {
property: 'reqDisplay',
sortProperty: 'reqDisplay'
},
Cheers, Oleg

How to inform a selectfield element from response of Ext.Ajax.request?

I need to inform a selectfield sencha element from callback of Ext.Ajax.request({})
I have a this code, for example,
Ext.Ajax.request({
url: '/express/EXPRESSVE00007_es.jsp',
timeout: 90000,
params: {
evento : action,
cookie: document.cookie,
NAME : Ext.getCmp("txtName").getValue(),
LAST : Ext.getCmp("txtLast").getValue(),
SEX : Ext.getCmp("txtSex").getValue()
},
success: function(r, o) {
var response = r.responseText
response = response.trim()
response = response.replace('\n', '').replace('\r', '')
var jsonResponse = Ext.decode(response)
Ext.Msg.alert(jsonResponse)
},
failure: function() {
Ext.Msg.show({
title: "Failure",
msg: "Error, failed response",
buttons: Ext.Msg.OK,
icon: Ext.MessageBox.ERROR
})
}
})
and my selectfield,
{
xtype: 'selectfield',
id: 'selSex',
name: 'select',
label: '*Sex',
placeHolder: 'Select...',
displayField: 'desc',
hiddenName: 'second-select',
options: [
{desc: '', value: ''},
{desc: '', value: ''}
]
}
In this case, I need to inform "desc" and "value" field from callback Ext.Ajax.request, but I don't know. Please help me.
You can inform the selectfield from an Ext.Ajax.request by updating it's store.
You could declare a store to store all the field values and then on response from the request, you can shuffle the data store to which selectfield is binded.
E.g
{
xtype: 'selectfield',
store: sampleStore,
valueField:'value',
displayField:'desc',
}
and update the store values on Ext.Ajax.request's response like this,
Ext.StoreMgr.get('sampleStore').load();
You can do below
Test = Ext.regModel('Test', {
fields: [{
name: 'desc',
type: 'string'
}, {
name: 'value',
type: 'string'
}]
});
exStores = new Ext.data.Store({
model: 'Test',
autoLoad: false });
and select field
{
xtype: 'selectfield',
store: exStores,
id: 'selSex',
name: 'select',
label: '*Sex',
placeHolder: 'Select...',
valueField:'value',
displayField:'desc',
}
and ajax request
Ext.Ajax.request({
...
success: function(r, o) {
var response = r.responseText
response = response.trim()
response = response.replace('\n', '').replace('\r', '')
var jsonResponse = Ext.decode(response)
exStores.loadData(jsonResponse, false);
Ext.Msg.alert(jsonResponse)
},
...
})
Hope this help.

ExtJs 4 comboboxes loading

I have to comboboxes. One of them contains regions and other contains cities. I want to achieve the wollowing behavior: when any region is selected in first combobox, avaliable cities in second combobox also change.
For example if I select Region1 in first combobox, then second combobox will contain CityA and CityB. If I select Region 2, second combobox will contain CityD, CityE and CityF.
I hope it was rather clear :)
I tried to solve it myself using closure style, but my code has an issue: combobox remains masked even when all cities are loaded. Does anyone know how to settle this problem?
Cities combobox code:
var setFilterRegion;
function getCityField() {
var citiesPerPage = 10;
var citiesProxy = Ext.create('Ext.data.proxy.Ajax', {
url: 'service/cities-data.php',
reader: Ext.create('Ext.data.reader.Json', {
root: 'cities',
totalProperty: 'totalCount'
})
});
setFilterRegion = function(regionId) {
citiesProxy.extraParams['region_id'] = regionId;
};
var cities = Ext.create('Ext.data.Store', {
pageSize: citiesPerPage,
model: 'City',
proxy: citiesProxy,
sorters: [{
property: 'name',
direction: 'ASC'
}]
});
var citiesComboBox = Ext.create('Ext.form.ComboBox', {
fieldLabel: 'Город',
store: cities,
displayField: 'name',
valueField: 'id',
listConfig: {
loadingText: 'Загрузка...',
emptyText: 'Нет городов с похожим названием'
},
pageSize: citiesPerPage,
labelWidth: contactInfo.labelWidth,
width: contactInfo.width
});
cities.loadPage(1);
return citiesComboBox;
}
Regions combobox code:
function getRegionField() {
var regionsPerPage = 10;
var regions = Ext.create('Ext.data.Store', {
pageSize: regionsPerPage,
model: 'Region',
proxy: Ext.create('Ext.data.proxy.Ajax', {
url: 'service/regions-data.php',
reader: Ext.create('Ext.data.reader.Json', {
root: 'regions',
totalProperty: 'totalCount'
})
}),
sorters: [{
property: 'name',
direction: 'ASC'
}]
});
var regionsComboBox = Ext.create('Ext.form.ComboBox', {
fieldLabel: 'Регион',
store: regions,
displayField: 'name',
valueField: 'id',
listConfig: {
loadingText: 'Загрузка...',
emptyText: 'Нет регионов с похожим названием'
},
pageSize: regionsPerPage,
labelWidth: contactInfo.labelWidth,
width: contactInfo.width
});
regions.loadPage(1);
return regionsComboBox;
}
Interaction code:
var regionField = getRegionField();
var cityField = getCityField();
var phoneField = getPhoneField();
regionField.on('change', function(t, newVal){
setFilterRegion(newVal);
cityField.getStore().loadPage(1);
});
Артём, take a look at his example, I think it's exactly what you need:
http://extjs.wima.co.uk/example/1
Elegant solution was found in this article:
http://www.learnsomethings.com/2011/05/17/where-did-setextraparam-aka-setbaseparam-go-in-extjs-4-%E2%80%93-one-workaround/