Extjs4 Accordion - inline link to go between panels - extjs

I have a basic ExtJS 4.0 accordion. I want to have an inline link within the text of one panel that will close that panel and open another.
In the example below, the link in Panel 1 should open Panel 2. What sort of click function would work here?
Ext.create('Ext.panel.Panel', {
title: 'Accordion Layout',
layout:'accordion',
layoutConfig: {
// layout-specific configs go here
titleCollapse: false,
animate: true,
activeOnTop: true
},
height: 300,
width: 400,
items: [{
title: 'Panel 1',
id: 'p1',
html: 'Text goes here. <p><a id="linkP2" href="#">Go to panel 2</a></p>'
},{
title: 'Panel 2',
id: 'p2',
html: 'Panel content!'
},{
title: 'Panel 3',
id: 'p3',
html: 'Panel content!'
}],
renderTo: Ext.getBody()
});​

Here is one that I did recently to change the expanded panel for a tab key navigation handler. My accordion panel was contained in a tabpanel so the first variable gets the active tab, you could change that however you want to get accordion panel itself as fits your needs, something like:
var tab = Ext.ComponentQuery.select(panel[layout=accordion]);
would work for you to get a reference to the accordion if this is the only accordion panel in your app.
// direction arg is either 1 or -1 depending on whether we want to go
// forward or backward
shiftPanels: function(direction) {
var tab = this.getMainPanel().getActiveTab(), // gets the active tab panel
panels = tab.items, // gets all of the accordion panels
active = tab.child('[collapsed=false]'), // gets the expanded panel
shifted;
// get the panel at direction + index (the panel we want to expand)
panels.each(function(panel, idx) {
if (active == panel) {
shifted = panels.getAt(direction + idx);
return false;
}
});
// expand the shifted panel or wrap around to the beginning or end
if (shifted) {
shifted.expand();
} else if (direction > 0) {
shifted = panels.getAt(0);
shifted.expand();
} else {
shifted = panels.getAt(panels.length - 1);
shifted.expand();
}
},

I ended up finding a rather simple solution:
<a id="linkP2" href="javascript:onClick=Ext.getCmp(\'p2\').expand();">Go to panel 2</a>
Ext.getCmp.expand allows the selection of a certain ID within the accordion.

Related

Accessing 2nd tab of tabpanel

I m getting undefined values while accessing grid rows of 2nd tab of tabpanel.
I have created a tabpanel with the following code:
xtype: 'tabpanel',
border: false,
deferredRender: true,
region: 'center',
activeTab: 0,
items:[{
id: 'availableoperators',
itemId: 'ops-operators-grid',
xtype: 'chat.dashboard.opsmall',
title: 'Operators',
region: 'center'
}, {
id: 'availableagents',
itemId: 'ops-agents-grid',
xtype: 'chat.dashboard.opsmgrid',
title: 'Agents',
region: 'center'
}]
Here I m trying to access rows of 2nd panel:
var opsGrid = Ext.getCmp('availableagents');
var records = opsGrid.store.getRange(0, opsGrid.store.getTotalCount());
for(var i = 0; i < records.length; i++) {
var row = opsGrid.getView().getRow(i);
}
The above code is working fine only if I use id of first tab. Any help would be appreciated.
It happens because component on the tab will be rendered at first shown. Store by default will be loaded after rendering of the grid on this tab. So you don't have rendered markup (the opsGrid.getView()) and don't have loaded data at store untill you opened the tab. If you will open second tab and manually run your code it should work fine.
Try to set deferredRender to false for the tabpanel, or forceLayout to true for your second tab. It will force rendering and loading all tabs (deferredRender:false) or only tab, there you will set forceLayout.
I'm going in the same way that Selmaril. Your view is not accessible. If you want, you can switch tab before the getView.
yourTabPanel.setActiveTab("availableagents");
yourTabPanel.doLayout();
Where yourTabPanel is the xtype: 'tabpanel', set it an id and you will be able to do:
Ext.getCmp("yourTabPanel").setActiveTab("availableagents");

ExtJS 4.2.1, treepanel disappearing

I am working with ExtJS 4.2.1
I have a button to make appear a panel.
This panel is containing my treepanel, five checkboxes below, and finally one valid button (to close the treepanel and valid the fact that we checked some nodes) and one cancel button (just to cose the treepanel).
I can make my panel appear and it works fine. But if I click on my cancel or my valid button, the panel will hide (ok), and next time I try to show it it doesn't contain my treepanel anymore, only the five checkboxes and the two buttons (attention, the two panels are different, the panel is containing my treepanel).
I don't understand because there is no reason for it to disappear. When I check the treepanel with some console.log() I can see, passing by treepanel.store.tree.root that my treepanel still exists and is properly filled. When I pass through treepanel.view.all I can see the right elements are present in my view. But when I check treepanel.body.dom with chrome debugging I can't see where the element is (ordinary when you pass over the dom with the mouse on chrome debugging you can see the corresponding part of the page colored).
Here is the concerned part of my code:
var button = Ext.get('ProductSelectionButton');
var treeSelector = createTree('stAddAction.do?action=product_tree_selector', 550, 490, '', 'lbl_st_tree_selection_empty', true, 'productlist');
button.on('click', function(){
treeSelector.store.proxy.url = 'stAddAction.do?action=product_tree_selector';
treeSelector.store.reload();
var productPanel = Ext.create('Ext.FormPanel',{
fieldDefaults:{
labelWidth: 75 // label settings here cascade unless overridden
},
frame:true,
title: document.getElementById('applicability').innerHTML + ' - ' + document.getElementById('lbl_st_product_tree_win').innerHTML,
style:'padding: 5px 5px 0; margin-top: 0;',
width: 550,
items: [treeSelector,
{
xtype: 'checkboxgroup',
items: [
{boxLabel: document.getElementById('lbl_status_deleted').innerHTML, name: 'status_2', checked: false, ctCls:'check-status-2',
listeners: {
change: function(newValue, oldValue, eOpts ){
if(newValue.checked){
// To show items with status 2 which is Deleted status
Ext.Array.remove(statusToHide, "2");
ProductList.showIdsStatus(2);
}
else{
// To hide items with status 2 which is Deleted status
Ext.Array.push(statusToHide, "2");
ProductList.hideIdsStatus(2);
}
}
},
... four others checkboxes
}],
buttons: [{
icon : 'img/st_little_valid.png',
style:'width:20px!important;',
handler: function(){
var data = '',
selNodes = treeSelector.getCheckedNodes(treeSelector.getRootNode());
precedentlyCheckedNodes = selNodes;
xhr = getXhr();
xhr.onreadystatechange = function(){
if (xhr.readyState == 4 && xhr.status == 200) {
var myLoad = eval(myDataGrid);
productgrid.store.loadData(myLoad);
productgrid.getView().refresh();
win.hide();
enableSave();
}
}
var params = "action=set_iceproduct&datatoadd=" + data + "&datatoremove=" + strUnchecked;
xhr.open("POST", "stAddAction.do", true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.setRequestHeader('Content-length', params.length);
xhr.send(params);
}
},
{
icon : 'img/st_little_cancel.png',
handler: function(){
/* restore all nodes how they were before (checked or unchecked) */
treeSelector.verifyCheckedNodes(precedentlyCheckedNodes);
win.hide();
/* Only expand the first level */
treeSelector.collapseAll();
treeSelector.getRootNode().expand();
}
}]
});
I don't know if it really is quite explicit...
Anyway, any idea could be welcomed!
How can this treepanel disappear from my panel and still exist!
Thank you
You are calling Ext.create in the buttons click event function every time. This means that the first time you create it, it's okay. But when you click the button again, it will create another panel with the same configuration, only you can't have treeSelector in both because it is already somewhere else. Change your code to something like:
var button = Ext.get('ProductSelectionButton');
var treeSelector = createTree('stAddAction.do?action=product_tree_selector', 550, 490, '', 'lbl_st_tree_selection_empty', true, 'productlist');
button.on('click', function(button){
treeSelector.store.proxy.url = 'stAddAction.do?action=product_tree_selector';
treeSelector.store.reload();
if(!button.productPanel)
{
button.productPanel = Ext.create('Ext.FormPanel',{
fieldDefaults:{
labelWidth: 75 // label settings here cascade unless overridden
},
frame:true,
title: document.getElementById('applicability').innerHTML + ' - ' + document.getElementById('lbl_st_product_tree_win').innerHTML,
style:'padding: 5px 5px 0; margin-top: 0;',
width: 550,
items: [
treeSelector,
{
xtype: 'checkboxgroup',
items: [
{boxLabel: document.getElementById('lbl_status_deleted').innerHTML, name: 'status_2', checked: false, ctCls:'check-status-2',
listeners: {
change: function(newValue, oldValue, eOpts ){
if(newValue.checked){
// To show items with status 2 which is Deleted status
Ext.Array.remove(statusToHide, "2");
ProductList.showIdsStatus(2);
}
else{
// To hide items with status 2 which is Deleted status
Ext.Array.push(statusToHide, "2");
ProductList.hideIdsStatus(2);
}
}

How to add layout dynamically in Exjs4?

I am working in Extjs4.And I am getting stuck at a point which is how to add accordion layout dynamically in Exjs4? I am using layout vbox and hbox but I als want to add accordion to east region.I tried a lot? but not getting succeed please some one give me some suggestion how to do it?
Ext.define('Am.view.Viewport', {
extend: 'Ext.container.Viewport',
layout: 'border',
id:'viewportId',
alias:'widget.Viewport',
autoScroll:true,
// closable:true,
items: [
{
region:'north',
items:[
{
xtype:'panel',
flex:.2,
title:'north region',
html:'<p>north region'
}
]//end of items
},
{
region:'west',
id:'westId',
//margins:'0 5 5 5',
flex:.3,
//layout:'accordion',
items:[
{
title:'This day in a history',
xtype:'Content'
}
]//end if items
},// end of region west
{
//title:'center',
region:'center',
id:'centerId',
//html:'center region',
items:[
]//End of itmes
},// end of region center
{
region:'east',
id:'eastId',
flex:.3,
items:[
{
xtype:'panel',
title:'panel1',
html:'hi<br>hello<br>good<br><br><br><br><br>morning<br>nice<br>looking',
},
{
xtype:'panel',
title:'panel2',
html:'hi<br>hello<br>good<br><br><br><br<br>noon<br>nice<br>looking',
},
{
xtype:'panel',
title:'panel3',
html:'hi<br>hello<br>good<br><br><br><br><brafter noon<br>nice<br>looking'
},
{
xtype:'panel',
title:'panel4',
html:'hi<br>hello<br>good<br><br><br><br><br><br><brnigth<br>nice<br>looking'
},
{
xtype:'panel',
title:'panel5',
html:'good bye'
},
]//end if items
},
{
//title:'South',
region:'south',
id:'southId',
items:[{
xtype:'panel',
title:"footer",
html:'footer '
}]
},//mainMenu // used mainMenu when you are using mainMenu variable
]//end if items
});//End of view port
I want to add accordion layout to east region dynamically.please give me some suggestion?
Why can't you just set the accordion layout in the config?
E.g.
{
region: 'east'
,layout: 'accordion'
,items: [
// ...
]
}
If you really want to change the region's layout to accordion dynamically, the problem you will encounter is that accordion layout needs to tweak its child components at render time. Or it will be broken. The simplest solution would be to add a copy of the original components, so that they can be rendered again.
You will also need to wrap your child components in another container, because accordion layout will need to be fitted in its parent container in order to work properly.
So, first you should change your east region config as follow:
{
region: 'east'
,id: 'eastId'
// set fit layout for children layout to work as intended
,layout: 'fit'
// wrap children into another container, that we can replace later
,items: [{
xtype: 'container'
,itemId: 'innerCt' // for easy access
,items: [
// ... your previous items
]
}]
// ... remaining of your region configuration
,flex: .3
}
And here's a function that changes east region's layout dynamically:
function changeEastLayout() {
var panel = Ext.getCmp('eastId'),
innerCt = panel.down('#innerCt'),
itemsCopy = [];
// make a copy of the item so accordion layout can render them like it likes
innerCt.items.each(function(item) {
itemsCopy.push(item.initialConfig);
});
// remove previous wrapper
panel.removeAll();
// adds a new wrapper with accordion layout containing the items copy
panel.add({
layout: 'accordion',
items: itemsCopy
});
}
If you wanted to change to another layout that doesn't need to affect the rendering of its children (e.g. hbox) you could use the original items instead of copies:
function changeEastLayout() {
var panel = Ext.getCmp('eastId'),
innerCt = panel.down('#innerCt'),
items = innerCt.removeAll(false); // autoDestroy to false
panel.add({
layout: 'vbox'
,items: items
});
// remove the wrapper container after in order to avoid destroying children
panel.remove(innerCt);
}

Can't redraw Panel in ExtJS

I made the sufficient investigation of this problem. But unfortunately didn't find any solution, even in stackoverflow questions, that look like this one.
I need to redraw(refresh, re-render) a panel, that contains a tabPanel with different tabs, that are rebuilding each time when I open the panel. Here is the code below to build tabs
//the first tab
categoryTpl: function(){
var categoriesTab = new Ext.Panel({
id: '_Categories',
title: 'X-Axis',
layout: 'form',
padding: 10,
labelWidth: 101,
items: [...]
})
}
Here is code to build the TabPanel
setAxesInfo: function(){
var categoryTab = this.categoryTpl();
//initialize the controls in the first tab
FC.Var.CM.initAxis(categoryTab, undefined);
delete this.axesTabPan;
this.axesTabPan = new Ext.TabPanel({
activeTab: 0,
plain: true,
enableTabScroll: true,
autoScroll: false,
defaults: { autoScroll: true },
items: [categoryTab]
});
}
This is the code to build Panel
create: function(){
this.setAxesInfo();
this.axes = new Ext.Panel({
layout: 'fit',
border: false,
items: this.axesTabPan
});
return {
id: 'axesStep',
title: 'Series Customization',
items: this.axes
}
}
So, I make changes in tab controls and then I want to rebuild(refresh, re-render) my panel I click the button, which have the next handler
refreshAxes: function() {
this.axes.removeAll();
this.setAxesInfo();
this.axes.add(this.axesTabPan);
this.axes.doLayout();
}
So, in debugger I can see, that all my controls in the tab have default initial values (they were rebuilt as I see). But in the browser I see only the previous changed values. It's notable, that if I change the focus of my panel (for example switch to another panel) and then return to this panel all data have the default values. Why I don't see the default values without loosing focus?
I am using the Ext Js 3.4 (this version is the requirement). I'll appreciate any help. Thank you.
Try doing a doLayout() on the Panel.

Building a TriggerField with PopUp Window

I built a triggerField and when i press at it, i want to have a popup, that is appended to the button in the triggerfield(so when i click anywhere else it shall disappear and it shall pop out up to the button when i click at the button just like a datepicker-popup)
I somehow managed to do something like that with an Ext.window but the offset and postion doesnt match.
This all should be contained in a row editor.
my Code:
new Ext.grid.GridPanel({
store: Store,
region:'center',
height:150,
//minWidth:700,
autoScroll:true,
listeners:{},
plugins:[new Ext.ux.grid.RowEditor()],
tbar: [{
iconCls: 'icon-user-add',
text: ' hinzufügen',
handler: function(){
alert("abc");
}
},{
ref: '../removeBtn',
iconCls: 'icon-user-delete',
text: 'löschen',
disabled: true,
handler: function(){
editor.stopEditing();
var s = grid.getSelectionModel().getSelections();
for(var i = 0, r; r = s[i]; i++){
store.remove(r);
}
}
}],
columns: [{
header: 'Monate',
dataIndex: 'MONAT',
width: 50,
sortable: true,
editor:
new Ext.form.TriggerField({"id":"EditorMonate",items:[],
"onTriggerClick":function(thiss){
if(!Ext.getCmp("autoWMonate")){
var monate=new Ext.Window({"x":Ext.getCmp("EditorMonate").x,closeAction:"hide",width:275,id:"autoWMonate",layout:"table",layoutConfig: {columns: 10}});
var text;
for(var mon=1;mon<13;mon++){
text=mon;
mon?mon:text="0";
if(mon<10)
text="0"+mon;
monate.items.add(
new Ext.Button({cls:"x-btn",value:parseInt(text),selected:true,"text":text,id:text
}}}));}
} Ext.getCmp("autoWMonate").hidden?Ext.getCmp("autoWMonate").show():Ext.getCmp("autoWMonate").hide();
}})
}
}]
})
Problem sovled with:
{
header: 'WochenTage',
dataIndex: 'WOCHE',
width: 100,
sortable: true,
editor: new Ext.form.TriggerField({
onTriggerClick: function(e) {
if (!this.menu) {
this.menu = new Ext.menu.Menu({
items:[{xtype:"label",text:"1"},{xtype:"label",text:"2"}]
// the items should have event listeners that set the field value accordingly
});
}
// here you would want to sync the items in the menu with the field value (this.getValue())
// before you show the menu -- keep in mind that the menu and its children might not be rendered yet
this.menu.showAt(e.getXY()); // or this.menu.show(this.getEl(), 'tl-bl?');
}
})
}
I did something like this by looking at the code of the date picker and generalizing the idea there - use a menu component for the popup behavior, and put whatever you like as a single component contained by the menu.

Resources