save the selected options rally - extjs

I have one Rally Sdk2 app, which has chooserDialog box.
Which displays programs, I can select multiple programs and click filter
then it displays the features for those programs but, when I again came to same dialog it does not store the last choices I made..
I tried stateful, but I am not getting it correct, below is my Dialog
And below is my ChooserDialog code
_run: function() {
var me = this;
Ext.create('Rally.ui.dialog.ChooserDialog', {
width: 470,
autoScroll: true,
height: 500,
title: 'Select to Filter',
pageSize: 100,
closable: false,
selectionButtonText: 'Filter',
itemId: 'chooser',
multiple: true,
setMultiple: true,
artifactTypes: ['PortfolioItem/Program','PortfolioItem/Epic','PortfolioItem/MMF'],
autoShow: true,
stateful: true,
stateId: 'selected-pi',
stateEvents: ['click','statesave'],
storeConfig:{
fetch: ['Name','PortfolioItemTypeName', 'Parent']
},
listeners: {
scope: me,
artifactChosen: function(selectedRecord) {
//this.down('#chooser').setValue(selectedRecord);
var filters = me._getFilters(selectedRecord);
me._drawCardBoard(me, filters);
}
}
});
},

This may or may not be possible in the rc builds of the SDK. We just made the new 2.0 version available and it has full support for the stateful mixin now.
There is even a guide for how to implement it:
http://help.rallydev.com/apps/2.0/doc/#!/guide/state
Also please note that the ChooserDialog is considered deprecated. The ArtifactChooserDialog should be a mostly drop-in replacement however.

I did not try State, but localstorage can be used to set default values:
localStorage.setItem('MyComboboxValue',Ext.getCmp('MyCombobox').getValue());
and get default values by setting value config property of the component to the value returned by:
value: localStorage.getItem('MyComboboxValue')
See a full code example of saving selections in comboboxes and checkboxes via localstorage in this github repo. The choices are retained after the page is reloaded.
UPDATE: I tried to make ArtifctChooserDialog remember selections, but it turns out that this code will not work in case of multiple selections when multiple: true due to a bug that Kyle identified.
Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
_selected: [],
stateful: true,
getState: function(){
return{
selectedRef: this.selectedRecord
}
},
launch: function() {
var that = this;
Ext.create('Rally.ui.dialog.ArtifactChooserDialog', {
itemId: 'dialog',
autoShow: true,
multiple: true,
artifactTypes: ['PortfolioItem/Theme','PortfolioItem/Initiative','PortfolioItem/Feature'],
storeConfig:{
fetch: ['Name','PortfolioItemTypeName']
},
listeners: {
scope: this,
artifactchosen: function(dialog, selectedRecord) {
this._selected.push(selectedRecord);
console.log(selectedRecord);
//this.selectedRecord = dialog.getSelectedRef();
this.selectedRecord = Rally.util.Ref.getRelativeUri(selectedRecord);
this.saveState();
}
},
selectedRef: this.selectedRef
});
}
});

Related

Duplicate references when reusing the same component in Sencha app

Suppose we have defined a component (e.g. FieldSet) that we'd like to reuse in the single app (e.g. display/use it in 2 different modal windows.) This FieldSet has a reference, which we use to access it. The goal is to have these 2 windows contain independent fieldsets, so we can control and collect the inputs from each one separately.
Here's the sample fiddle that demonstrates the problem. As soon as any function triggers any lookupReference(...) call, Sencha issues the warning for "Duplicate reference" for the fieldset. It correctly creates two distinct fieldset components (by assigning different ids) on each window, but fails to properly assign/locate the references. As a result, any actions on one of these windows' fieldsets would be performed on the "unknown" one (probably on the first created one), messing up the UI behavior.
I see how it is a problem for Sencha to understand which component to use when operating on the reference, but there should be a way to reuse the same component multiple times without confusing the instances. Any help is greatly appreciated.
According to the docs on ViewController:
A view controller is a controller that can be attached to a specific view instance so it can manage the view and its child components. Each instance of the view will have a new view controller, so the instances are isolated.
This means that your use of singleton on your ViewController isn't correct, as it must be tied to a single view instance.
To fix this, I'd recommend making some modifications to your Fiddle, mainly removing the singleton: true from your VC class, accessing the views through lookup, and getting their VC's through getController to access your func method.
Ext.application({
name: 'Fiddle',
launch: function () {
/**
* #thread https://stackoverflow.com/questions/67462770
*/
Ext.define('fsContainerHandler', {
extend: 'Ext.app.ViewController',
alias: 'controller.fsContainerHandler',
// TOOK OUT singleton: true
func: function () {
var x = this.lookupReference('fsRef');
alert(x);
}
});
Ext.define('fsContainer', {
extend: 'Ext.container.Container',
xtype: 'xFSContainer',
controller: 'fsContainerHandler',
items: [{
xtype: 'fieldset',
title: 'myFieldset',
reference: 'fsRef'
}]
});
Ext.define('mainContainerHandler', {
extend: 'Ext.app.ViewController',
alias: 'controller.mainContainerHandler',
singleton: true,
onButton1Click: function () {
var win = this.getView().window1;
win.show();
// CHANGED LOGIC
win.lookup('theContainer').getController().func();
},
onButton2Click: function () {
var win = this.getView().window2;
win.show();
// CHANGED LOGIC
win.lookup('theContainer').getController().func();
}
});
Ext.define('mainContainer', {
extend: 'Ext.container.Container',
width: 400,
controller: 'mainContainerHandler',
window1: null,
window2: null,
initComponent: function () {
this.window1 = Ext.create('window1');
this.window2 = Ext.create('window2');
this.callParent(arguments);
},
items: [{
xtype: 'button',
text: 'Window 1',
reference: 'btn1',
handler: mainContainerHandler.onButton1Click,
scope: mainContainerHandler
}, {
xtype: 'button',
text: 'Window 2',
reference: 'btn2',
handler: mainContainerHandler.onButton2Click,
scope: mainContainerHandler
}]
});
Ext.define('window1', {
extend: 'Ext.window.Window',
title: 'Window1',
modal: true,
width: 100,
height: 100,
closeAction: 'hide',
// ADDED referenceHolder
referenceHolder: true,
items: [{
xtype: 'xFSContainer',
// ADDED reference
reference: 'theContainer'
}]
});
Ext.define('window2', {
extend: 'Ext.window.Window',
title: 'Window2',
modal: true,
width: 100,
height: 100,
closeAction: 'hide',
// ADDED referenceHolder
referenceHolder: true,
items: [{
xtype: 'xFSContainer',
// ADDED reference
reference: 'theContainer'
}]
});
Ext.create('mainContainer', {
renderTo: document.body
});
}
});

ExtJS 6 - Issue while adding new items to accordion panel

I have a new ExtJS 6 application and Im trying to populate an accordion menu.
Note: This same code works perfect in ExtJS 4.2.
This is the accordion component:
Ext.define('MyApp.view.menu.Accordion', {
extend: 'Ext.panel.Panel',
alias: 'widget.mainmenu',
width: 350,
split: true,
layout: {
type: 'accordion',
autoScroll: true,
autoHeight: true,
titleCollapse: false,
animate: false,
activeOntop: true
},
collapsible: true,
floatable: false,
hideCollapseTool: false,
title: 'MenĂº',
});
Now, I have in my ViewController a store that I load, this is the code:
var menuPanel = Ext.ComponentQuery.query('mainmenu')[0];
storeMenu.load({
callback: function(records, op, success) {
menuPanel.removeAll();
Ext.each(records, function(rec) {
var title = rec.data.title;
var menu = Ext.create({
xtype: 'treepanel',
rootVisible: false,
title: 'This is a test'
});
menuPanel.add(menu);
});
menuPanel.updateLayout();
}
});
My store records count = 7, so I should see 7 items added to my menu, but this is what I get:
If I again do the same but adding a breakpoint in my debuggin console (image below)
Then my result is the following:
The issue is breaking my head and is really very strange, it works if I debugg adding a breakpoint in order it to work.
Any clue on this issue?
Try adding them in one call:
storeMenu.load({
callback: function(records, op, success) {
var panels;
Ext.suspendLayouts();
menuPanel.removeAll();
panels = Ext.Array.map(records, function(rec){
var title = rec.get('title');
return {
xtype: 'treepanel',
rootVisible: false,
title: title
};
});
menuPanel.add(panels);
Ext.resumeLayouts(true);
}
});

Grid State is not being saved when more than once instance used

If I have more than one instance of a Grid I have numerous problems. One problem is that the saving of state (ie. sorting, filter widths etc.), doesn't work properly. Saving of state is reset when I navigate to another instance of the same Grid. However if I am on the page with just one grid, I can click on refresh, and change things about, and everything saves OK. Its just when i navigate to a screen with another instance of my grid.
Yes, I am setting a different stateId for the two instances, and I am making a call to Ext.state.Manager at the start of the application :
Ext.state.Manager.setProvider(Ext.create('Ext.state.CookieProvider'));
The creation of an instance looks like this :
this.packageGrid = Ext.create('js.grid.PackageGrid', {
stateId: 'CompletePackageGrid', //for my other instance I obviously use a different string here
width: 979,
height: 400,
});
And my Grid code looks like this :
Ext.define('js.grid.PackageStore', {
extend: 'Ext.data.JsonStore',
model: 'js.model.Package',
remoteFilter : false,
remoteSort: false
});
var createColumns = function () {
var columns = [{
dataIndex: 'id',
text: 'ID',
width: 80,
filter: {
type: 'int'
}
}, {
dataIndex: 'packageName',
text: 'Name of Packet',
width: 300,
filter: {
type: 'string'
}
}, {
}];
return columns;
};
Ext.define('js.grid.PackageGrid', {
extend: 'Ext.grid.Panel',
title: '',
multiSelect: true,
autoExpandColumn: 'name',
loadMask: true,
stateful: true, //*******STATEFUL!!!!
filterable: true,
initComponent : function (){
this.columns = createColumns();
this.initialConfig.columns = this.columns;
this.store = new js.grid.PackageStore();
this.plugins = {
ptype: 'bufferedrenderer',
trailingBufferZone: 20, // Keep 20 rows rendered in the table behind scroll
leadingBufferZone: 50 // Keep 50 rows rendered in the table ahead of scroll
};
this.viewConfig = {
stripeRows: true,
enableTextSelection: true
};
this.features = {
ftype: 'filters',
encode: false,
local: true
};
this.callParent();
}
});
I have tried to put as much code into my initComponent method, so there is less risk of objects being shared.
How does the code for my Grid look? Is there anything there that would explain this problem?

How to send AJAX Request only if store size is 0

How to send AJAX request for combo box by having condition that current store size is 0.
Basically I have two remote combo box which are cascaded and both are lazily loaded ( This behaviour cannot be changed)
I found even if the second combo box is cascaded based on events in first combobox upoun expansion it makes AJAX call to server ( Only first expansion though)
querymode local and autoload option will not work as it load the combo box on page load when store is created.
Given below is code snippet.
xtype: 'combo',id='firstcombo', name: 'DEFAULT_VALUE' ,minChars:2, value: decodeHtmlContent('') ,width:200 ,listWidth:500, resizable: true,
valueField : 'id', displayField: 'id', pageSize: 15,forceSelection:true, enableKeyEvents: true,
store: new Ext.data.Store({reader: new Ext.data.CFQueryReader({id: 'NAME',
fields:[{name:'id', mapping:'id'}]}),
fields: [{name:'id', mapping:'id'}],
url:'server/ajax/Params'
}
}),
listeners : {
select:function(combo, record, index) {
this.setRawValue(decodeHtmlContent(record.get('id')));
cascadeFields();
}
xtype: 'combo',id='secondcombo', name: 'DEFAULT_VALUE' ,minChars:2, value: decodeHtmlContent('') ,width:200 ,listWidth:500, resizable: true,
valueField : 'id', displayField: 'id', pageSize: 15,forceSelection:true, enableKeyEvents: true,
store: new Ext.data.Store({reader: new Ext.data.CFQueryReader({id: 'NAME',
fields:[{name:'id', mapping:'id'}]}),
fields: [{name:'id', mapping:'id'}],
url:'server/ajax/Params',
baseParam:{valuefirst:''}
},
listeners: {
beforeload: function(store, options) {
var value = Ext.getCmp('fistcombo').value;
Ext.apply(options.params, {
valuefirst:value
});
},
}),
listeners : {
select:function(combo, record, index) {
this.setRawValue(decodeHtmlContent(record.get('id')));
}
function cascadeFields()
{
var combo = Ext.getCmp('secondcombo');
if(combo.store)
{
var store = combo.store;
combo.setDisabled(true);
combo.clearValue('');
combo.store.removeAll();
combo.store.load();
combo.setDisabled(false);
}
}
To just extend your code you can do it Like so
listeners: {
beforeload: function(store, options) {
if (store.getCount() > 0) {
return false; // will abort the load operation.
}
var value = Ext.getCmp('fistcombo').value;
Ext.apply(options.params, {
valuefirst:value
});
}
}
This should work all the same in ExtJS 3.x and ExtJS4.x cause you didn't specified this. But I guess you are using 3.x
If this hangs the combo give me feedback cause there is still another but a bit more complex way.

Update or Reload Store of ExtJs ComboBox

I'd like to know a way of how to update or reload the list values of a ExtJs ComboBox. For instance, I have a some checkboxes. These checkboxes determine what values the ComboBox should have. So, after selecting some of those, I click the drowndown list (combobox) to see the values.
In short, how can I change the values (store) of a ComboBox already has.
Hope someone can help me
Thanks
I've been using this undocumented ExtJs API function to change the store at runtime:
mycombobox.bindStore(newStore);
as stated by the support team in http://www.sencha.com/forum/showthread.php?40749-Change-Combobox-store-data-update.
Edit: If I want to put the new data when the store is populated, I do something like this
storeMyStore = new Ext.data.Store({
...
listeners: {
load: function(this, records, options) {
cbMyCombo.bindStore( storeMyStore );
}
}
});
It goes a little something like this
{
xtype: 'checkbox',
//configs
listeners : {
checked : function (checkbox, checkedBool) {
var yourCombo = Ext.getCmp(yourComboID);
//I'm not sure what params you will need to reload the comboBox from your
// service but hopfully this will give the jist of things. . .
yourCombo.store.reload(
{
params:
{yourParam : checkedBool},
{yourRowID : rowID}
});
}
}
Here I making a combobox that is updated after a selection is made on another ComboBox.
Basically, the final user can use the two comboboxes to select a main category and a sub-category, which is based on the selection made on the first combobox.
This is the store for First comboBox:
Ext.define("StoreSubject", {
extend: "Ext.data.Model",
fields: [
{
name: 'i_Id'
},
{
name: 's_Value'
}
]
});
var StoreSubject = Ext.create('Ext.data.JsonStore', {
model: 'StoreSubject',
proxy: {
type: 'ajax',
url: '../General/AdministrationDefaultXMLDOM.aspx?qid=15',
reader: {
type: 'json'
}
}
});
StoreSubject.load();
This is the store for Second comboBox:
Ext.define("StoreLanguageGroup", {
extend: "Ext.data.Model",
fields: [
{
name: 'i_Id'
},
{
name: 's_Value'
}
]
});
var StoreLanguageGroup = Ext.create('Ext.data.JsonStore', {
model: 'StoreLanguageGroup',
proxy: {
type: 'ajax',
url: '../General/AdministrationDefaultXMLDOM.aspx?qid=16',
reader: {
type: 'json'
}
}
});
My code for Comobox is looks like this..
First ComboBox :
var cmbSubjectName = Ext.create('Ext.form.field.ComboBox', {
id: 'cmbSubjectName',
fieldLabel: '<b>Subject</b>',
name: 'cmbSubjectName',
valueField: 's_Value',
displayField: 's_Value',
allowBlank: false,
anchor: '80%',
labelWidth: 150,
emptyText: '[--Choose--]',
minChars: 0,
store: StoreSubject,
queryMode: 'local',
typeAhead: true,
listeners: {
'select': {
fn: function (combo, value) {
var strSubjectName = Ext.getCmp('cmbSubjectName').getValue();
Ext.getCmp('cmbLanguageType').clearValue();
Ext.getCmp('cmbLanguageType').getStore().load({
params: {
SubjectName: strSubjectName
}
});
}
}
},
});
This code is used to call and override the combox store (Impotent otherwise it will keep on loading )
Ext.override(Ext.LoadMask, {
onHide: function () {
this.callParent();
}
});
//---------------------------
Second ComboBox :
var cmbLanguageType = Ext.create('Ext.form.field.ComboBox', {
id: 'cmbLanguageType',
fieldLabel: '<b>Language</b>',
multipleSelect: false,
name: 'cmbLanguageType',
valueField: 's_Value',
displayField: 's_Value',
allowBlank: false,
anchor: '80%',
labelWidth: 150,
emptyText: '[--Choose--]',
minChars: 0,
store: StoreLanguageGroup,
queryMode: 'local',
typeAhead: true,
});
Hope this will helps you.. and Please rate my answer
In an event listener on the checkboxes, get a reference to the store that your ComboBox is reading from. Then invoke its add or remove functions to update the data in the store based on what check box is checked Once the updates are complete, invoke a doLayout() on the ComboBox component, it should re-render itself based on the current state of the store.
Although I think there is a way to have it automatically update any time the store updates -- I haven't used that yet.

Resources