Force Ext to create body element for hidden (collapsed) panel - extjs

I've created a panel bundled with an Ext.Template. This panel is contained in another panel that starts its life collapsed.
id: 'myPanel',
title: 'My Title',
layout: 'border',
collapsible: true,
collapsed: true,
hideCollapseTool:true,
bodyBorder: false,
height: 300,
bodyStyle: 'background:#F9F9F9;',
items: [{
id: 'myDisplayPanel',
bodyStyle: 'background:transparent;',
width: 300,
border: false,
margins: '5 5 5 5',
region: 'west',
tpl: new Ext.Template([
'some template'
])
},
{
id: 'myForm',
xtype: 'form',
bodyStyle: 'background:transparent;',
border: false,
margins: '5 5 5 5',
region: 'center',
[...]
This template-panel is supposed to be updated as the result of a row select in a neighbouring grid. But I get an error the first time I call .update(data); on the myDisplayPanel, as it contains no body element.
myGridSelectionModel: new Ext.grid.RowSelectionModel({
singleselect: true,
listeners: {
rowselect: function(sm,rowIdx,r) {
Ext.getCmp('myDisplayPanel').update(r.data);
Ext.getCmp('myPanel').expand(true);
}
}
}),
The call to myDisplayPanel.update() causes an error when Ext tries to call the template.overwrite function with myDisplayPanel.body as the first param.
function(b,a,c){b=Ext.getDom(b);b.innerHTML=this.applyTemplate(a);
Is it possible somehow to force Ext to generate a body element for this hidden panel before it is beeing shown? I've tried to expand the element prior to updating it, but this has now effect...

I know this thread is 2 months old, so I'm not sure if you ever found a solution. However, I just ran into the same thing and came across your thread while looking for an answer. This is what I ended up doing:
Where you're currently running panel.update(content), try this:
if(panel.rendered) panel.update(content);
else panel.contentToLoad = content;
Set up a listener for the render event to run:
if(this.contentToLoad) panel.update(this.contentToLoad);
That way, if the panel isn't rendered, it will store the content somewhere and the render listener will load whatever is there when the panel IS rendered.

Collapsed panels (and hidden containers in general) by default do not layout their children until they first become visible. You can override this behavior by setting forceLayout: true on the collapsed container. As the name suggests, this will force the container to perform its layout whether it is visible or not. Note that in your case this would be myPanel that would need this configuration, not myDisplayPanel.

You might try Panel's elements config, which from the docs is "A comma-delimited list of panel elements to initialize when the panel is rendered." So e.g.,
elements: ['header','body']
However it already defaults to 'body' only, so it may just be that the panel is truly not rendered yet when you are updating it. Try reversing the order of your calls so that the container is expanded first (should force the child panel to render) then update it.

Related

tui-calendar doesn't display properly in ExtJS panel

I've been looking at adding a simple calendar to an ExtJS app and like the features of the tui-calendar.
I've started with just trying to display a month in a panel. I've tried various layouts, length and width configs, but the calendar never fully displays. Here's a fiddle showing the results.
Any ideas what I'm missing?
Thanks in advance,
Gordon
You can use layout: 'fit' on the panel and set the div's width and height to 100% with html style, like <div id="calendar" style="width:100%;height:100%"></div>. This way you:
tell the panel (which has a fixed size) that it will have one child that should occupy all available area,
tell the div which contains the calendar to use 100% of the available place horizontally and vertically.
Ext.create('Ext.panel.Panel', {
renderTo: document.body,
height: 600,
width: 600,
layout: 'fit',
tbar: [{
xtype: 'button',
text: 'Display Calendar',
handler: function (button) {
const container = document.getElementById('calendar');
calendar = new tui.Calendar(container, options);
calendar.setDate('2023-03-01');
}
}],
items: [{
html: '<div id="calendar" style="width:100%;height:100%"></div>',
xtype: 'component'
}]
});
I'd like to note that I am not sure that this way ExtJS will manage the life cycle of the calendar object. I would recommend to keep track of the created calendar object and destroy it when the panel is destroyed. To do so, add a destroy listener event to the panel and destroy the calendar object there.

Updating and rerendering components in ExtJS 4.2

Is there a way to re-render components upon tab switch? I have this data that loads all its store, which contains specific permissions. Each tab must only contain what was provided for their view. See my screenshot below:
Basically, this loads upon initComponent. The dilemma I'm currently having is that the Backoffice tab has a different permission with the Wombat tab. The idea is when either of them contains a permission say an Edit permission (sCreate), only that role is allowed to show the edit buttons as seen. So Backoffice has sEcommCreate while Wombat has sCreate. When either of them satisfies to true, it simply adds/pushes it to the column to be displayed during initComponent.
if (EcommBackoffice.plugin.Security.getAccess(oMe.sCreatePermission)) {
aColumns.push({
header: 'Action',
xtype: 'actioncolumn',
itemId: 'edit-role-btn',
width: 100,
sortable: false,
resizable: false,
draggable: false,
menuDisabled: true,
items: [{
icon: 'resources/img/editpermissions.png',
tooltip: 'Edit Permissions',
scope: oMe
}],
editor: {
xtype: 'text',
name: 'editRow',
cls: 'banks-delete-row'
}
});
}
How do I filter out the display upon switching on the other tab, and also on load? Currently, once sCreate or sEcommCreate passes its condition, it just adds the buttons on both roles since this is one single store.
Already tried reloading the data store from the controller, but it
only loads the data, and not rerender the components to either
add/remove/show/hide them.
To be more clear, I need to hide/remove the Action column if it has no create permissions assigned to it.
The actioncolumn and all actioncolumn items have a function isDisabled. I would recommend to use that function to enable/disabled the item, e.g.
items: [{
icon: 'resources/img/editpermissions.png',
tooltip: 'Edit Permissions',
isDisabled:function() {
var isWombatTab = (this.up('tabpanel').getActiveTab().text == 'Wombat');
if(isWombatTab) return EcommBackoffice.plugin.Security.getAccess(oMe.sCreatePermission)
else return EcommBackoffice.plugin.Security.getAccess(oMe.sEcommCreatePermission)
},
scope: oMe
}],
isDisabled() will be processed during grid refresh, so whenever you reload the store, the changes should come into effect. To force a refresh without changes to the store, you could of course call grid.refresh() from the activate event of the tabs.
It should then possible to hide the disabled item via CSS. I don't know exactly what it will take (may also depend e.g. on the theme you use), but a first guess is
.x-grid-cell-edit-role-btn .x-item-disabled {
visibility:hidden;
}

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.

Ext.form.combobox inside ext.window displays values at top left of screen

I have a combobox inside of a ext.panel, inside of an ext.window. When I click the down arrow to show the possible SELECT options, the options pop up at the top-left of the browser window, instead of below the SELECT box. The funny thing is if I attach the drugDetailsPanel (see code below) to a div on the page (instead of inside an ext.window), the combobox works correctly. This also happens when I change ext.panel to ext.form.formpanel, by the way.
Any ideas?
My code:
drugDetailsPanel = new Ext.Panel({
layout:'form',
id:'drug-details-panel',
region:'center',
title:'Drug Details',
height:200,
collapsed:false,
collapsible:false,
items:[
new Ext.form.ComboBox({
fieldLabel:'What is the status of this drug?',
typeAhead:false,
store:drugStatusStore,
displayField:'lookup',
mode:'remote',
triggerAction:'all',
editable:false,
allowBlank:false,
emptyText:'Select a status..',
name:'/drug/drug-status',
id:'drug-status'
})
]
});
newDrugWindow = new Ext.Window({
title: 'Add Drug',
closable:true,
width:650,
height:650,
//border:false,
plain:true,
layout: 'border',
items: [drugDetailsPanel],
closeAction:'hide',
modal:true,
buttons: [
{
text:'Close',
disabled:false,
handler: function(){
newDrugWindow.hide();
}
},
{
text:'Save Drug',
handler: function(){
newDrugDialog.hide();
}
}]
});
Try to add shim: true to combo-box control.
Older versions of Ext had issues like this in certain browsers (FF 2.x) in certain situations dealing with nested positioning, the specifics of which escape me now. If that's the case, search the Ext forums for more info. If not, then I'm not sure...
This forum thread helped me: http://www.sencha.com/forum/showthread.php?177677-IE-displays-combobox-dropdown-in-the-top-left-corner-of-browser-window
Just give the combobox a (unique) name. Giving the combobox an inputId should also help
Seems like IE does not respect the position of the element if it does not have an explicit name/inputId. This thread goes more deeply into it: http://www.sencha.com/forum/showthread.php?154412-Combo-Box-options-appears-in-Top-Left-Corner-in-IE-9

ExtJs Combobox Resize Problem on IE6

A Combobox in the following constellation (extremely pruned code) has problems resizing in IE6. A little debugging revealed that it doesn't receive an event when trying to shrink the west region via splitter.
Ext.onReady(function(){
var grid = new Ext.Viewport({
layout: 'border'
,items: [{
region: 'west'
,width: 200
,layout: 'fit'
,split: true
,items: [{
layout: 'accordion'
,items: [{
layout: 'Anchor'
,items: [{
xtype: 'combo'
,anchor: '100%'
,typeAhead:true
,triggerAction: 'all'
,selectOnFocus: true
,mode: 'local'
,emptyText: 'bitte wählen'
,displayField: 'displayText'
,store: new Ext.data.ArrayStore({
fields: ['displayText'],
data: [['item1'], ['item2']]
})
}]
}]
}]
},{
region: 'center'
,html: 'content'
}
]
,renderTo: Ext.getBody()
});
});
It only happens within an accordian layout. Investigate that further.
Ext.onReady(function() {
var grid = new Ext.Viewport({
layout: 'border'
,items: [{
region: 'west'
,width: 200
,split: true
--,layout: 'fit' << not necessary. You're overnesting.
,layout: 'anchor'
,items: [{
xtype: 'combo'
,anchor: '100%'
,typeAhead:true
,triggerAction: 'all'
,selectOnFocus: true
,mode: 'local'
,emptyText: 'bitte wählen'
,displayField: 'displayText'
,store: new Ext.data.ArrayStore({
fields: ['displayText'],
data: [['item1'], ['item2']]
})
}]
},{
region: 'center'
,html: 'content'
}]
})
});
The above works fine for me in IE6
I hope this helps you.
Extract from AnchorLayout doc:
AnchorLayout does not have any direct
config options (other than inherited
ones). However, the container using
the AnchorLayout can supply an
anchoring-specific config property of
anchorSize. By default, AnchorLayout
will calculate anchor measurements
based on the size of the container
itself. However, if anchorSize is
specifed, the layout will use it as a
virtual container for the purposes of
calculating anchor measurements based
on it instead, allowing the container
to be sized independently of the
anchoring logic if necessary.
The items added to an AnchorLayout can
also supply an anchoring-specific
config property of anchor which is a
string containing two values: the
horizontal anchor value and the
vertical anchor value (for example,
'100% 50%'). This value is what tells
the layout how the item should be
anchored to the container. The
following types of anchor values are
supported:
Percentage: Any value between 1 and
100, expressed as a percentage. The
first anchor is the percentage width
that the item should take up within
the container, and the second is the
percentage height. Example: '100% 50%'
would render an item the complete
width of the container and 1/2 its
height. If only one anchor value is
supplied it is assumed to be the width
value and the height will default to
auto.
Offsets: Any positive or
negative integer value. The first
anchor is the offset from the right
edge of the container, and the second
is the offset from the bottom edge.
Example: '-50 -100' would render an
item the complete width of the
container minus 50 pixels and the
complete height minus 100 pixels. If
only one anchor value is supplied it
is assumed to be the right offset
value and the bottom offset will
default to 0.
Sides: Valid values are
'right' (or 'r') and 'bottom' (or
'b'). Either the container must have a
fixed size or an anchorSize config
value defined at render time in order
for these to have any effect.
I had a similar problem. Try putting the combobox in a container. So instead of putting it directly in the panel with the anchor layout, put the combo in a container and add this container to the panel with the anchor layout! It should work!

Resources