Updating and rerendering components in ExtJS 4.2 - extjs

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

Related

Duplicate reference when maximizing/restoring dialog

When maximizing/restoring a dialog that contains some form fields with names, like:
Ext.create('Ext.Dialog', {
maximizable: true,
items: {
xtype: 'textfield',
name: 'id',
bind: '{record.id}'
},
buttons: [{
text: 'Save',
bind: {
disabled: '{!record.valid}'
}
}]
}).show();
we're getting an error:
Ext.mixin.Container.attachNameRef(): Duplicate name: "id" on ext-viewport between ext-textfield-1 and ext-textfield-5
Two found workarounds :
Disable animation
Ext.define('Override.Dialog', {
override: 'Ext.Dialog',
config: {
maximizeAnimation: false,
restoreAnimation: false
}
});
Make the proxy used for animation have no items (nor buttons since button disable state may not reflect the bounded value
Ext.define('Override.Dialog', {
override: 'Ext.Dialog',
config: {
maximizeProxy: {
items: null,
buttons: null
}
}
});
Background Information
During maximize and minimize ExtJS creates a shadow clone.
This will create a clone of the window, while you still have the original item.
Using an ID means, there can only be one identical one at any given time.
The clone tries to create the your textfield with the same ID, which does not work.
Typically you want to
for forms you usually do not need to grab each item as you can work with validator and getValues on the form
otherwise you might want to work with references in the view and lookupReference in the controller.
not use animation (because that does not create a clone)
write your own maximize animation and do the animation part yourself (write your own maximize function)

How to determine which menu item I'm working with in changeHandler with ExtJs?

When a menu item is selected and my changeHandler is invoked (function(cycleBtn, activeItem)), what ExtJs mechanism is recommended to be used to determine which item I'm working with?
Using the text of the item is not ideal as it may change. Other frameworks often provide a value attribute which may differ from the actual text displayed which can be relied on to accurately determine which item you're working with.
Does ExtJs have a property I can reference on the selected menu item to accurately ascertain which item I'm working with to act upon? Obviously, I'd set this in advance too.
You can use itemId instead of id because itemId is local to the container, menu in this case. You only need to make sure that itemIds of menu items are unique in that menu.
You can use activeItem's id but you need to know that if you change the code the id will change as well. So, you can't trust the id for unique. If you give an unique id for each item's of the menu, id become unique in whole application.
Ext.create('Ext.button.Cycle', {
showText: true,
prependText: 'View as ',
renderTo: Ext.getBody(),
menu: {
id: 'view-type-menu',
items: [{
text: 'text only',
iconCls: 'view-text',
checked: true
},{
text: 'HTML',
iconCls: 'view-html'
}]
},
changeHandler: function(cycleBtn, activeItem) {
console.log(activeItem.id)
}
});
// view-type-menu is an unique id
console.log(Ext.getCmp('view-type-menu'));

Extjs 4 FiltersFeature vs stateful grid

I have a grid with some columns with filters.
columns defination:
columns:[{
text: "Number",
dataIndex: 'clientreference',
width: 200,
filter: true,
sortable: true
},
here is filter feature defination
features: [{
ftype: 'filters',
encode: true,
local: false
}],
The problem is: When i'm trying to save state of grid, filters are not working: When I adding this code to a grid:
stateful: true,
stateId: 'documentsGrid',
I refresh the page and all works fine, because i dont have state in my cookies.
But when I refresh the page second time - state loads from cookies and filters are not working.
If i remove stateful: true and refresh page, filters are working fine.
Any suggestions?
Also I noticed, that all examples in extjs site are only with filters or with stateful grid, but there is no one example with both.
UPDATED:
The most useful way was making my own method for saving state of elements I need and to restore it.
I think you are specifying features in grid.But you can specify filters in store directly.So try to define filters in store and stateful in grid config options.Hope you may get the solution to come out from this.

Ext js combobox does not display all items in menu

Can someone tell me how to get rid of the feature that filters combo box items.
when i click on the trigger of the combo, i want to display ALL menu items regardless of what text is already in the box, NOT filtered. I've tried several different config options with no luck.
make sense ?
for example, if i have 'View' as my text in the combo, and i click on the trigger, it will only show 'View1' and 'View2' items, i want it to include all the others...
Thanks!
heres my current config
{
...
items: [{
xtype: 'combo',
id: 'myViewsCombo',
emptyText: 'Select View',
selectOnFocus: true,
listeners: {
select: function(combo, record, index) {
L3.handlers.loadView(combo.value);
}},
store: ['View1', 'View2','blahblah']
}]
}
Setting triggerAction: "all" solved the same problem for me.
Try the setting the 'disableKeyFilter' config option to true.
See the ext combobox api.

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

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.

Resources