How to add layout dynamically in Exjs4? - extjs

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);
}

Related

Want to reload ExtJs tab panel each time it is rendered

I'm creating a set of ExtJs Panels & TabPanel in a jsp page as:
//left panel
var leftpanel = new Ext.Panel({
id :'leftpane',
region:'west',
width: leftPaneDefaultWidth,
layout : 'fit',
header : false,
split:true
});
//right tabpanel
var rightpaneltab = new Ext.TabPanel({
id:'rightpanetabs',
border:false,
enableTabScroll: true,
region:'center'
});
//parent panel
var toppanel = new Ext.Panel({
id : 'main',
layout:'border',
renderTo : 'parentDiv',
items: [ leftpanel , rightpaneltab ]
});
Owing to a business requirement, I need to refresh/reload the contents within the rightpaneltab defined above.
Could someone pls suggest an optimal away of achieving this?
You can listen to events like painted, show, initialize and some others.
Check the documentation here: https://docs.sencha.com/extjs/6.7.0/modern/Ext.tab.Panel.html#event-initialize
initialize - Fires when the component has been initialized
painted - Fires whenever this Element actually becomes visible (painted) on the screen. This is useful when you need to perform 'read' operations on the DOM element, i.e: calculating natural sizes and positioning.
show - Fires whenever the Component is shown
Usage:
//left panel
var leftpanel = new Ext.Panel({
id :'leftpane',
region:'west',
width: leftPaneDefaultWidth,
layout : 'fit',
header : false,
split:true
});
//right tabpanel
var rightpaneltab = new Ext.TabPanel({
id:'rightpanetabs',
border:false,
enableTabScroll: true,
region:'center',
listeners: {
painted: function () {
// reload the content here
}
}
});
//parent panel
var toppanel = new Ext.Panel({
id : 'main',
layout:'border',
renderTo : 'parentDiv',
items: [ leftpanel , rightpaneltab ]
});

ExtJs 5.0 - appending html in Viewport

I'm trying to build a rating system on my help page using following rating widget
https://github.com/christophe-g/Ext.ux.widget.Rating
I've a viewport with following sections:
/********* WEST REGION *********/
var helpTree = Ext.create('Ext.tree.Panel', {
id : 'helpTree',
useArrows : true,
region : 'west',
collapsible : true,
listeners :{
itemclick : function(node, record, item, index, e){
// Get contents using AJAX and update it in center region of viewport.
getAndUpdateHelpContents(record.get('id'));
}
},
});
/******** CENTER REGION ********/
var helpTab = Ext.create ('Ext.tab.Panel', {
id : 'helpTab',
region:'center',
activeTab:0,
items:{
id : 'helpItemTab',
title: 'Contents',
html: '<h4>Welcome to Help System<h4>',
},
});
var rating = new Ext.ux.widget.Rating({
id : 'ratingField',
fieldLabel : 'Rating',
allowBlank : false,
value : 2.5,
titles: {
'0': 'poor',
'1.4': 'medium',
'3': 'excellent',
'5': 'perfect'
},
});
/******** SOUTH REGION ********/
var ratingTab = Ext.create ('Ext.form.Panel', {
id : 'ratingTab',
region:'south',
layout : 'anchor',
margins: '5 5 5 0',
items:[rating]
});
/******** VIEWPORT ********/
Ext.create('Ext.container.Viewport', {
renderTo: Ext.getBody(),
layout: 'border',
items: [
helpTree,
helpTab,
ratingTab
]
});
Now in this design, rating widget is in south region. Instead, I wish to remove south region and append rating widget at the bottom of the contents of center region after calling "getAndUpdateHelpContents" function as this function clears and updates the contents in center region whenever user clicks a link on left/west region/tree. Following is this function in jquery
function getAndUpdateHelpContents(id, text) {
htmlContents = "<p>This is Test</p>";
$("#helpItemTab").html(htmlContents);
}
Pls help as in how to append this rating at the end of center region contents (after dynamic loading)!
Thanks.
Generally, you do not need any html markup in Ext to add a component to it. The required markup is generated by Ext and by the widget automatically.
When you have a container (Panel is also a container) then you can call ct.add(rating) - the widget is added to the panel as the last item.
You probably don't want to add it on each click in the listener you indicated.

extjs - How to define a window as unique ?

Is there a way to define a window as unique ?
What I mean exactly is: when the window is already open, I want it to get focus, instead of opening it again.
For now my menu click event just does:
onMenuItemClick: function(){
Ext.create('Mb.view.UniqueWindow').show()
},
Give it a unique id, then verify if it already exists before creating it, otherwise just show it, something like
function onMenuItemClick() {
var wnd = Ext.getCmp('myUniqueWindow');
if (!wnd) {
wnd = Ext.create('Ext.window.Window', {
id: 'myUniqueWindow',
title: 'Unique Window',
height: 200,
width: 400,
layout: 'fit',
closeAction: 'hide', // This is really important otherwise closing it will destroy the window!
items: { // Let's put an empty grid in just to illustrate fit layout
xtype: 'grid',
border: false,
columns: [{
header: 'Hello World'
}], // One header just for show. There's no data,
store: Ext.create('Ext.data.ArrayStore', {}) // A dummy empty data store
}
});
} else {
wnd.getEl().highlight()
}
wnd.show();
}
You can see a working sample here
Save a reference to it:
if (!MyApp.someWin) {
MyApp.someWin = new Ext.window.Window();
}
MyApp.someWin.show();

Extjs4 Accordion - inline link to go between panels

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.

ExtJS Pop-up Window Form data loading

I use Grid panel. When I select the row in the grid I get the following results:
If I render the Form in 'document.body' everything is OK, and form
fields are filled.
If I, same Form start in Window panel, Form fields are empty.
When I use both, Form which is rendered in the 'document.body' is
closed, and Form fields in Window are filled.
Where I make mistake.
// Grip panel part
sm: new Ext.grid.RowSelectionModel({
singleSelect: true,
listeners: {
rowselect: function(sm, index, record) {deleteWindow.show();}
}
})
// End Grid panel part
var myForm = new Ext.form.FormPanel({
title:"Basic Form",
width:425,
frame:true,
items: [
new Ext.form.TextField({
id:"to",
fieldLabel:"To",
width:275,
allowBlank:false,
blankText:"Please enter a to address",
readOnly: true
}),
new Ext.form.TextField({
id:"subject",
fieldLabel:"Subject",
width:275,
allowBlank:false,
blankText:"Please enter a subject address",
readOnly: true
}),
],
buttons: [
{text:"Cancel"},
{text:"Save"}
]
});
var deleteWindow = new Ext.Window({
id: 'id_deleteWindow',
title: 'Delete',
closable:true,
width: 750,
height: 380,
plain:true,
layout: 'fit',
items: myForm
});
var id_test = 2; // This is only for this problem
//myForm.render(document.body); // When using this code everything is ok, and form fields are filled
myForm.getForm().load({
url:'ggg.php',
params:{
id: id_test
}
});
JSON data
{success:true,results:[{"id_test":"1","to":"a","subject":"aa"}]}
I would suggest the following changes to the code:
In place of using the id property on the TextField (say, id: 'subject'), use name property (name: 'subject')
Just curious....since you are handling the rowselect event on the grid, you might want to load the selected record in the form panel rather than loading it again. If this is the case, then you may call the loadRecord() method on the form panel and pass the record object to it and then call the show() method on the window
I figured out that when load is called on form, ExtJS tries to access form dom element to determine form method. I've found 2 solutions:
Add method to the form config
Load data to form after window is showed
Here is code for second solution:
var deleteWindow = new Ext.Window({
id: 'id_deleteWindow',
title: 'Delete',
closable:true,
width: 750,
height: 380,
plain:true,
layout: 'fit',
items: myForm,
listeners: {
show: function() {
var form = this.items.get(0);
form.getForm().load({
url:'ggg.php',
params:{
id: id_test
}
});
}
}
});
deleteWindow.show();

Resources