afterrender not work in tbpanel Extjs modern - extjs

Afterrender event not work for my tabpanel component.
code of my tabpanel:
Ext.define('Admin.view.tabs.Tabs', {
extend: 'Ext.tab.Panel',
shadow: true,
cls: 'demo-solid-background',
tabBar: {
layout: {
pack: 'center'
}
},
activeTab: 1,
defaults: {
scrollable: true
},
items: [
{
title: 'Tab 1',
html : 'By default, tabs are aligned to the top of a view.',
cls: 'card'
},
{
title: 'Tab 2',
html : 'A TabPanel can use different animations by setting <code>layout.animation.</code>',
cls: 'card'
}
],
listeners: {
afterrender: function(corpse) {
console.log('afterrender');
}
}});
This tab panel I use in view formpanel that added in main view like this:
doCompose: function (to) {
var me = this,
composer = me.composer,
view = me.getView(),
viewModel = me.getViewModel(),
toField;
me.hideActions();
if (!composer) {
me.composer = composer = view.add(
{
xtype: 'compose',
flex: 1
});
if (to) {
toField = me.lookupReference('toField');
toField.setValue(to);
}
viewModel.set('composing', true);
}
}
Compose it's my formpanel which contain tabpanel.
I try use example from official templates ExtJs Sencha.
View for mobile profile compose email https://github.com/syscobra/extjs-admin-dashboard-template/tree/master/modern/src

As i said Ext-JS 6 modern TabPanel has not afterrender event.Instead you can use painted, heres the
FIDDLE
listeners: {
painted: function () {
//your code
}
}

Related

TabPanel not Render or Show tabs

I have a simple app presentation with a set of windows with sencha components. When a event of move previous window or move next window the main controller take the view, clean it and add a new component to view...
Ext.define('jsclient.view.main.MainVC', {
extend: 'Ext.app.ViewController',
alias: 'controller.main-view',
config: {
listen: {
global: {
eventNewWindow: 'eventNewWindow'
}
}
},
eventNewWindow: function (callback) {
this.view.removeAll();
this.view.add(callback());
}
});
The problem occurs when i put a panel component that contains a tabpanel, the components paint all window, paints the tabs, but no paint the components that contain each tab. If i exam the components that window create, its was created but not render or showing.
Ext.define('jsclient.view.articleCheck.ArticleCheckV', {
extend: 'Fwk.Panel',
alias: 'widget.article-check',
controller: 'article-check',
viewModel: 'article-check',
requires: [
'Fwk.Panel',
'Ext.TabPanel',
'jsclient.view.articleCheck.ArticleCheckVM',
'jsclient.view.articleCheck.ArticleCheckVC',
'jsclient.view.articleCheck.articlePending.ArticlePendingV',
'jsclient.view.articleCheck.articleChecked.ArticleCheckedV'
],
cls: 'article-check',
title: 'Mi ventana**',
titleAlign: 'center',
layout: {
type: 'vbox',
align: 'fit'
},
items: [{
xtype: 'tabpanel',
flex: 1,
deferredRender: true,
items: [{
title: 'Pendientes',
reference: 'pending',
xtype: 'article-pending',
width: "50%"
}, {
title: 'Chequeados',
reference: 'checked',
xtype: 'article-checked',
width: "50%",
}]
}],
tools: [{
type: 'left',
docked: 'left',
listeners: {
click: {
element: 'element',
fn: 'goPrevious'
}
}
}, {
type: 'plus',
docked: 'right',
margin: '0 20 0 0',
listeners: {
click: {
element: 'element',
fn: 'goNewArticle'
}
}
}],
listeners: {
click: {
element: 'element',
fn: 'prueba'
}
},
constructor: function (config) {
this.callParent([config]);
}
});
Any code have two file more that helps viewmodel component, i will saw you a example above.
The View:
Ext.define('jsclient.view.main.MainV', {
extend: 'Fwk.Panel',
alias: 'widget.main-view',
id: 'main-view',
requires: [
'Fwk.Panel',
'jsclient.view.main.MainVM',
'jsclient.view.main.MainVC',
'jsclient.view.blockCheck.BlockCheckV',
'jsclient.view.centerList.CenterListV',
'jsclient.view.articleCheck.ArticleCheckV',
'jsclient.view.articleCheck.articlePending.ArticlePendingV',
'jsclient.view.articleCheck.articleChecked.ArticleCheckedV'
],
viewModel: 'main-view',
controller: 'main-view',
layout: {
type: 'vbox',
align: 'fit'
},
margin: 'auto',
items: [{
xtype: 'center-list',
flex: 1
}],
constructor: function (config) {
this.callParent([config]);
//Read url params and restore context if needed
var urlParams = location.search;
if (urlParams !== '') {
Fwk.Context.restore(urlParams);
}
}
});
The Controller:
Ext.define('jsclient.view.main.MainVM', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.main-view',
data: {},
stores: {}
});
Well, to my problem i doesn't find a solution in the way i'm trying solved... But using a different point of view i can solved.
My oldest way, create items on a component:
This solution might be correct but... for tabpanel doesn't work. I create a component in viewport (main component) and in this component when a event happend i create a new component.
-> Viewport
|
-> MainComponent
|
-> AnyComponent (event)
Using this piece of code i try modified the view main with a callback that return the
constructor of new component in main view:
/*
* Callback in other view
*/
callback: function(options){
return new jsclient.view.mycomponent.MyComponentV(options);
}
/*-----------------------------*/
eventNewWindow: function (callback) {
this.view.removeAll();
this.view.add(callback());
}
My new way create items on viewport:
The new solution is similar but use Viewport instead main component, We need have some
things clear. Viewport is a set (Array) of views that compete for main view, if not are
on main view, the components is on second plane and they not are visible but are init.
So solution left like that, instead use main component we use viewport:
We create N controller for N view, and when a other view send a global event, the controller catch the event and itself create here on viewport.
Ext.define('jsclient.controller.main.MainController', {
extend: 'Ext.app.Controller',
requires: [
'jsclient.view.main.i18n.Main_en_EN',
'jsclient.view.main.i18n.Main_es_ES',
'jsclient.view.main.MainV',
],
config: {
listen: {
global: {
eventNewMain: 'eventNewMain'
}
}
},
eventNewMain : function(options) {
Ext.Viewport.setActiveItem('main-view');
}
});
In the case we need pass argument to component we can do this piece of code:
Ext.define('jsclient.controller.articleCheck.ArticleCheckController', {
extend: 'Ext.app.Controller',
requires: [
'jsclient.view.main.i18n.Main_en_EN',
'jsclient.view.main.i18n.Main_es_ES',
'jsclient.view.articleCheck.ArticleCheckV',
],
config: {
listen: {
global: {
eventNewArticleCheck: 'eventNewArticleCheck'
}
}
},
eventNewArticleCheck: function (options) {
if(options != undefined){
Ext.Viewport.removeAll();
}
Ext.Viewport.add({
xtype: 'article-check',
options: { block: options }
});
Ext.Viewport.setActiveItem('article-check');
}
});

Define listeners in controller ExtJS

I have got the tabpanel - it's the main form (view).
In this tabpanel I define the different tabs - xtype:'panel'.
So, I have one main(controller) , main view and some tabs views.
The tab's views are referenced in main view.
I want to define listener of activate event of some child's panel in main controller.
How can I do that?
the main controller :
Ext.define('KP.controller.account.apartment.Main', {
extend: 'Ext.app.Controller',
views: ['account.apartment.Main',
'account.apartment.Requisites'
],
models: ['account.apartment.Requisites'
],
stores: ['account.apartment.Requisites'
],
init: function () {
}
});
The main view:
Ext.define('KP.view.account.apartment.Main', {
extend: 'Ext.window.Window',
alias: 'widget.ApartmentData',
height: 566,
width: 950,
activeItem: 0,
layout: {
type: 'fit'
},
autoShow: false,
initComponent: function() {
var me = this;
Ext.applyIf(me, {
items: [
{
xtype: 'tabpanel',
activeTab: 0,
deferredRender: true,
items: [
{
xtype: 'RequisitesApartment'
}
]
}
]
});
me.callParent(arguments);
}
});
The child panel RequisitesApartment (view):
Ext.define('KP.view.account.apartment.Requisites', {
extend: 'Ext.panel.Panel',
alias: 'widget.RequisitesApartment',
id: 'panel_accountrequisites',
height: 350,
width: 1124,
autoScroll: true,
layout: {
type: 'fit'
},
listeners: {
activate: function () {
....load data....
...this listeners I want to push in 'main' controller...
}
},
initComponent: function () {
var me = this;
var grid_store = Ext.create('KP.store.account.apartment.Requisites');
Ext.applyIf(me, {
dockedItems: [
{
xtype: 'gridpanel',
height: 260,
autoScroll: true,
dock: 'bottom',
store: grid_store,
id: 'r_gridFlatParams',
forceFit: true,
columns: [
...some columns....
],
viewConfig: {
}
}
]
});
me.callParent(arguments);
}
});
Register it directly as control within the responsible controller
Here is a example with a working query. For sure you just will need the query, but I think it's a good example. The custom cfg property ident make it easy find each tab. As in the example below you will have specify a tabConfig within each panel and define the ident there.
Ext.create('Ext.tab.Panel', {
width: 400,
height: 400,
renderTo: document.body,
items: [{
title: 'Foo',
tabConfig: {
ident: 'foo'
},
}, {
title: 'Bar',
tabConfig: {
ident: 'bar',
title: 'Custom Title',
tooltip: 'A button tooltip'
}
}]
});
console.log(Ext.ComponentQuery.query('tabpanel tabbar tab[ident=foo]')[0]);
console.log(Ext.ComponentQuery.query('tabpanel tabbar tab[ident=bar]')[0]);
Another way is to use css id's which can be queried like '#my-name' but I recommend to use a custom one as in the example above
Well, I should put this code in 'main'(controller):
this.control({
'ApartmentData tabpanel RequisitesApartment': {
activate: function () {
console.log('hello!');
}
}
});
The problem was in wrong selector , that I used.
The correct selector is :
'ApartmentData tabpanel RequisitesApartment'
There 'ApartmentData'(define like a alias: 'widget.ApartmentData') - is the 'window' xtype -the main form.
tabpanel - panel with tabs in 'window', and 'apartServList'(define like alias: 'widget.RequisitesApartment') - the some panel.
Thanks for sra!
the correct thing to do is to pass a config object to the member function control into controller init function. From Sencha documentation : The control function makes it easy to listen to events on your view classes and take some action with a handler function.
A quick example straight from extjs docs:
Ext.define('MyApp.controller.Users', {
extend: 'Ext.app.Controller',
init: function() {
this.control({
'viewport > panel': {
render: this.onPanelRendered
}
});
},
onPanelRendered: function() {
console.log('The panel was rendered');
}
});
Hope this helps.
Cheers

click listener for tab panel in EXTJS

i use a tab panel in extjs. I want to display an alert when clicked on a tab. But i am not sure how.
This is what i do now:
{
xtype: 'tabpanel',
activeTab: 0,
region: 'center',
items: [
{
xtype: 'panel',
title: 'All',
items: [grid]
},
{
xtype: 'panel',
title: 'Closed'
},
{
xtype: 'panel',
title: 'Open'
}
],
listeners: {
click: function () {
alert('test');
}
}
}
How can is display All, Closed or Open when there is clicked on that tab?
There is no event for tab click in TabPanel, however you can bind into click event on each tab:
Ext.createWidget('tabpanel', {
items: [...],
listeners: {
render: function() {
this.items.each(function(i){
i.tab.on('click', function(){
alert(i.title);
});
});
}
}
});
Notice: this is ExtJS 4 based code.
I manage to do this by using tabchange event. In example below I used newCard.xtype property where value of xtype (i.e. task-archive) is just my panel with controls and corresponding xtype property.
Ext.define('ComplexBrigade.controller.taskArchive.TaskArchive', {
extend: 'Ext.app.Controller',
init: function() {
this.control({
'#tabWorks': {
tabchange: this.doTest
}
});
},
doTest: function ( tabPanel, newCard, oldCard, eOpts) {
switch (newCard.xtype) {
case "task-archive":
console.log("task-archive");
break;
case "task-creation":
console.log("task-creation");
break;
}
}
});

ExtJS Toolbar button highlite

Iam design menu in ExtJs using Ext.Toolbar,
var ToolBar = new Ext.Toolbar({
id: 'ToolBar',
renderTo: 'divtoolbar',
items: [
{ xtype: 'spacer', width: 50 },
{ xtype: 'tbbutton', text: 'Home', handler: function () { window.location = '#Url.Content("~/Home/Home/")'; } },
{ xtype: 'tbseparator' },
{ xtype: 'tbbutton', text: 'Calendar', handler: function () { window.location = '#Url.Content("~/calendar/eventCalendar/")'; } },
{ xtype: 'tbseparator' },
{ xtype: 'tbbutton', text: 'Locations' }
]
............
how to change or highlite clicked tbbutton
thanks in advance
You need to make use of the addClass method available with the button. Create a CSS style for the visited button and call addClass method in handler. Here is an example:
handler: function(b,e) {
this.addClass('className');
}
But in your case, I see that you are navigating away from the page. In such cases you will have to store the visited buttons in a cookie or use HTML5 storage.
I wonder why you are making a multipage ExtJS application and not following the single page approach?

Extjs: Reuse the same grid in TabPanel

in a Extjs application I have a Grid and a Tabs line over it. Content of the Grid depends on the selected Tab.
Say tabs has Jan-Feb-Mar-... values. Clicking of the Tab I would reload grid's store
Question: is it possible to avoid duplicating of the 12 grid components in favor to have one shared instance?
Thanks
Disclaimer: searching at the sencha's forum, google, stackoverflow was not successful :(
It is, but it would require more effort than it is worth. Just create a prototype for your component, so that you can create new instances really quickly.
I haven't tried this myself, but I imagine that you could create a TabPanel with empty tabs and size the TabPanel so that only the tab strip is visible. Under that (using the appropriate layout, border, vbox, etc.) create your GridPanel and use the TabPanel's activate event to reload the grid based on the currently-active tab.
Hope the following implementation meet your needs
1. Create your custom grid and register it
2. place it tab panel
As the grid is created using xtype, it would not create 12 instances when you change tabs.
Application.PersonnelGrid = Ext.extend(Ext.grid.GridPanel, {
border:false
,initComponent:function() {
Ext.apply(this, {
store:new Ext.data.Store({...})
,columns:[{...}, {...}]
,plugins:[...]
,viewConfig:{forceFit:true}
,tbar:[...]
,bbar:[...]
});
Application.PersonnelGrid.superclass.initComponent.apply(this, arguments);
} // eo function initComponent
,onRender:function() {
this.store.load();
Application.PersonnelGrid.superclass.onRender.apply(this, arguments);
} // eo function onRender
});
Ext.reg('personnelgrid', Application.PersonnelGrid);
var panel = new Ext.TabPanel({
items:[{
title:'Jan',
items: [{xtype:'personnelgrid'}]
}, {
title: 'Feb',
items: [{xtype:'personnelgrid'}]
}
....
{
title: 'Dec',
items: [{xtype:'personnelgrid'}]
}]
})
Since this is the only place discussed about this until now, I share what I just found.
The trick is use dockedItems in ExtJs 4 (Not sure either grid can be added into tbar in ExtJs 3)
When changing the active tab, only body will be change but not the docked item. Just set the grid height equal to the body during boxready and resize so that we can't see the body anymore.
This is the code for ExtJs 4.2 MVC that also make use of refs.
Ext.define('app.controller.Notification', {
extend: 'Ext.app.Controller',
views: ['notification.List'],
stores: ['Notification'],
models: ['Notification'],
refs: [{
ref: 'pnlNotif',
selector: 'pnlNotif'
}, {
ref: 'notifList',
selector: 'notifList'
}],
init: function () {
this.control({
'dbPnlNotif': {
added: this.pnlNotifAdded,
boxready: this.calcNotifListSize,
resize: this.calcNotifListSize,
tabchange: this.pnlNotifTabChange
}
});
},
pnlNotifAdded: function (pnlNotif) {
pnlNotif.add({ title: '1', html: '1' });
pnlNotif.add({ title: '2', html: '2' });
pnlNotif.add({ title: '3', html: '3' });
},
calcNotifListSize: function (pnlNotif) {
// calc the notification list height to make sure it use the whole body
// This way we can use only one instance of list to display for each tabs
// because the list is rendered as dockedItems
var height = pnlNotif.getHeight();
var headerHeight = pnlNotif.getDockedItems()[0].getHeight();
var tabBarHeight = pnlNotif.getDockedItems()[1].getHeight();
height = height - headerHeight - tabBarHeight;
if (this.getNotifList().getHeight() !== height) {
this.getNotifList().setHeight(height - 1);// - 1 to include border bottom
}
},
pnlNotifTabChange: function (pnlNotif, newTab) {
// do something to filter the list based on selected tab.
}
});
Ext.define('ML.view.Notification', {
extend: 'Ext.tab.Panel',
alias: ['widget.pnlNotif'],
title: 'Notification',
dockedItems: [{
xtype: 'notifList'
}]
});
Ext.define('ML.view.notification.List', {
extend: 'Ext.grid.Panel',
alias: 'widget.notifList',
dock: 'top',
store: 'Notification',
initComponent: function () {
this.columns = [
...
];
this.callParent(arguments);
}
});
Try this
var gridJanName = Ext.create('Ext.grid.Panel', {
enableColumnHide: false,
autoScroll:true,
store: storeJanNameGroup,
border:true,
stripeRows: true,
columnLines:false,
loadMask: true,
tbar:tbgridTools,
margin: '1 1 1 1',
pageSize: 100,
maxWidth:700,
features: [groupFeature],
selModel: {
mode: 'MULTI'
},
columns: [
{xtype:'rownumberer',width:50},
{dataIndex:'id', hidden:true},
//etc
]
});
var gridFebName = Ext.create('Ext.grid.Panel', {
enableColumnHide: false,
autoScroll:true,
store: storeJanNameGroup,
border:true,
stripeRows: true,
columnLines:false,
loadMask: true,
tbar:tbgridTools,
margin: '1 1 1 1',
pageSize: 100,
maxWidth:700,
features: [groupFeature],
selModel: {
mode: 'MULTI'
},
columns: [
{xtype:'rownumberer',width:50},
{dataIndex:'id', hidden:true},
//etc
]
});
//
//etc grid
//
var JanPanel = Ext.create('Ext.panel.Panel', {
title:'Jan',
bodyPadding: 5,
Width:780,
layout: {
type: 'hbox',
align: 'stretch'
},
items: [gridJanName]
});
var FebPanel = Ext.create('Ext.panel.Panel', {
title:'Feb',
bodyPadding: 5,
Width:780,
layout: {
type: 'hbox',
align: 'stretch'
}
//,items: [gridFebName]
});
var MarPanel = Ext.create('Ext.panel.Panel', {
title:'Mar',
bodyPadding: 5,
Width:780,
layout: {
type: 'hbox',
align: 'stretch'
}
//,items: [gridMarName]
});
//etc
var eachMonthstabs = Ext.create('Ext.tab.Panel', {
minTabWidth: 130,
tabWidth:150,
//Width:750,
scroll:false,
autoHeight: true,
id:'timestabs',
enableTabScroll:true,
items: [
{
xtype:JanPanel
},
{
xtype:FebPanel
},
{
xtype:MarPanel
}
///etc
]
});
For me good solution was to use a left toolbar called lbar with list of buttons and a single grid instead of tabpanel

Resources