How to add new childs dynamically from json to treenode in extjs4 - 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'
});

Related

the experimental hierarchical tree for rally

I see that Hierarchical trees are labeled as experimental on the Rally site (https://help.rallydev.com/apps/2.0rc3/doc/#!/api/Rally.ui.grid.TreeGrid). I wanted to build an app using the hierarchical tree and I had a few questions about the features. Is it possible to filter the tree or no? Also can i add up the totals of the tasks for a given userstory (estimate, todo, actual, etc) and list that total as the userstory value? Is there another way to get a list of the userstories with the tasks in a list beneath it?
A not-treegrid example: this app that uses group and summary features in a grid of tasks in current iteration grouped by workproduct (user story), where Estimate values of individual tasks are summed up. Full code is in this github repo.
launch: function() {
var that = this;
var today = new Date().toISOString();
var stories = Ext.create('Rally.data.wsapi.Store', {
model: 'UserStory',
fetch: ['Tasks'],
filters: [
{
property: 'Iteration.StartDate',
operator: '<=',
value: today
},
{
property: 'Iteration.EndDate',
operator: '>=',
value: today
}
]
});
stories.load().then({
success: this.loadTasks,
scope: this
}).then({
success:function(results) {
that.makeGrid(results);
},
failure: function(){
console.log("oh noes!")
}
});
},
loadTasks: function(stories){
console.log("load tasks",stories)
var promises = [];
_.each(stories, function(story){
var tasks = story.get('Tasks');
if (tasks.Count > 0) {
tasks.store = story.getCollection('Tasks',{fetch:['Name','FormattedID','Estimate','State','Blocked','WorkProduct']});
promises.push(tasks.store.load());
}
});
return Deft.Promise.all(promises);
},
makeGrid: function(results){
var tasks = _.flatten(results);
var data = [];
_.each(tasks, function(task){
data.push(task.data);
})
_.each(data, function(record){
record.Story = record.WorkProduct.FormattedID + " " + record.WorkProduct.Name;;
})
this.add({
xtype: 'rallygrid',
showPagingToolbar: true,
showRowActionsColumn: true,
editable: false,
store: Ext.create('Rally.data.custom.Store', {
data: data,
groupField: 'Story',
}),
features: [{ftype:'groupingsummary'}],
columnCfgs: [
{
xtype: 'templatecolumn',text: 'ID',dataIndex: 'FormattedID',width: 100,
tpl: Ext.create('Rally.ui.renderer.template.FormattedIDTemplate'),
summaryRenderer: function() {
return "Estimate Total";
}
},
{
text: 'Name',dataIndex: 'Name',
},
{
text: 'State',dataIndex: 'State',xtype: 'templatecolumn',
tpl: Ext.create('Rally.ui.renderer.template.ScheduleStateTemplate',
{
states: ['Defined', 'In-Progress', 'Completed'],
field: {
name: 'State'
}
})
},
{
text: 'Estimate',dataIndex: 'Estimate',
summaryType: 'sum',
},
{
text: 'WorkProduct',dataIndex: 'WorkProduct',
renderer: function(val, meta, record) {
return '' + record.get('WorkProduct').FormattedID + '';
}
},
]
});
}
Update: If you want to filter the task store include a filter here:
tasks.store = story.getCollection('Tasks',{fetch:['Name','FormattedID','Estimate','State','Blocked','WorkProduct'],filters:{property: 'State',operator: '<',value: 'Completed'}});
A treegrid example: Rally.ui.grid.TreeGrid you referred is still a work in progress. I have not seen a working example of a story hierarchy using a treegrid but it does not mean it's impossible.
When I tested a story hierarchy, child stories did not appear under epic stories, however a story/task hierarchy worked. The filtering worked too. Here is an example:
Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
launch:function(){
Ext.create('Rally.data.wsapi.TreeStoreBuilder').build({
models: ['userstory'],
autoLoad: true,
filters:[
{
property: 'Name',
operator: 'contains',
value: 'story'
}
],
enableHierarchy: true
}).then({
success: function(store) {
var grid = Ext.create('Ext.Container', {
items: [{
xtype: 'rallytreegrid',
columnCfgs: [
'Name',
'Owner'
],
store: store
}]
});
that.add(grid);
}
});
}
The screenshot below shows that tasks are nested under a child story as expected,but the child story is not nested under parent. The grid is filtered by Name as expected:

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

Creating sorted tree in DOJO 1.6?

I new to learn dojo and trying to learn by it using samples code.
Using dojo 1.6
With help of sample codes , I created a tree
now i want to apply sorting on root and also on child.
With the help of this sample code , i changed the code
Output is not sorted n but the root folder has changed their position and child is deleted.
Plz help me to resolve this.
My code :
dojo.require("dojo.data.ItemFileWriteStore");
dojo.require("dojo.data.ItemFileReadStore");
dojo.require("dijit.tree.ForestStoreModel");
dojo.require("dijit.Tree");
var data = [ { id: 1, name: "answerTypeLabel", type:'scenario', children:[{_reference: 2}]},
{ id: 2, name: "acceptRequestLabel", type:'paragraph', data: "acceptRequestLabel"},
{ id: 3, name: "rejectRequestLabel", type:'scenario', children:[{_reference: 5},{_reference: 6}]},
{ id: 4, name: "MoreInformationLabel", type:'scenario', children:[{_reference: 7},{_reference: 8}]},
{ id: 5, name: "rejectRequestStatusLabel", type:'paragraph', data: "rejectRequestStatusLabel"},
{ id: 6, name: "rejectRequestNotCoveredLabel", type:'paragraph', data: "rejectRequestNotCoveredLabel" },
{ id: 7, name: "MoreInformationDocumentLabel", type:'paragraph', data: "MoreInformationDocumentLabel"},
{ id: 8, name: "MoreInformationDataLabel", type:'paragraph', data: "MoreInformationDataLabel"}
];
dojo.addOnLoad(function() {
var sortableStore = new dojo.data.ItemFileReadStore({
data: {
identifier: 'id',
label: 'name',
items: data
}
});
var model = new dijit.tree.ForestStoreModel({
rootLabel: 'Names',
store: new dojo.data.ItemFileWriteStore({
data: {
identifier: 'id',
items: [],
label: 'name'
}
}) // blank itemsstore
})
var tree = new dijit.Tree({
model: model,
updateItems: function(items) {
var self = this;
console.log('pre', this.model.root.children);
dojo.forEach(items, function(newItem) {
console.log('add', newItem);
try {
self.model.store.newItem({
id: sortableStore.getValue(newItem, 'id'),
name: sortableStore.getValue(newItem, 'name'),
type: sortableStore.getValue(newItem, 'type'),
data: sortableStore.getValue(newItem, 'data'),
});
} catch (e) {
console.log(e);
}
});
console.log('post', this.model.root.children);
console.log("children: ", this.rootNode.getChildren());
},
});
tree.placeAt(dojo.body());
sortableStore.fetch({
query: {
type:'scenario'
},
sort: [{
attribute: "name"}],
onComplete: function(items) {
console.log(items, 'sorted');
tree.updateItems(items);
}
})
});
Output :
The 'Names' origins from you setting 'rootLabel'.
Btw, fiddles have revisions and is simply a paste-bin like feature :)
You need to use the tree model pasteItem to insert referenced items (the 'children' property of each 'newItem').
Otherwise, there's another approach, if you get rid of the '_reference' structure of your data. See: http://jsfiddle.net/GHFdA/1/

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/