ExtJS button handler not working - extjs

My ExtJS button's handler is not invoked after clicking. Now the code looks like this.
Ext.define('EDS.view.selector.Container', {
extend: 'Ext.form.Panel',
alias : 'widget.selectorcontainer',
title: 'Selector_V2',
renderTo: 'input-div',
layout: 'fit',
height: '100%',
items: [
{
xtype: 'tabpanel',
defaults: {
bodyPadding: 10
},
}
],
buttons: [
{
text: 'Reset',
handler: function(){
console.log("Reset");
this.up('form').getForm().reset();
}
},
{
text: 'Add to constrain',
handler: this.addConstrain,
}
],
/*
* Logic for button "Add to constrain"
*
* Adds an entry into the constrain list describing a person, cost center or an application
*/
addConstrain: function(button, event){
console.log('Add_to_constrain clicked');
}
});
Originally this 'selectorcontainer' was put diretly in my app.js. But I extracted it into a stand-alone view. Before the extraction, it works perfect but now it is not working.
BTW, I've two buttons and the first "reset" works fine. So I'm wondering if there's anything wrong with "this.addConstrain" related to scoping.

You're right, it is a scoping issue - this is not the class you're defining; it's the scope at the time the Ext.define function is called (likely window). There are a few ways to handle this. The easiest (in my opinion) is to change your handler to work similarly to your reset handler:
{
text: 'Add to constrain',
handler: function(btn, e) {
//'this' is now the button
this.up('selectorcontainer').addConstrain(btn, e);
}
}
You could also add the buttons as part of the initComponent function instead of defining them as part of the Ext.define config.
initComponent: function() {
//'this' is now the selector container
this.buttons = [{
text: 'Reset',
handler: function(){
console.log("Reset");
this.up('form').getForm().reset();
}
}, {
text: 'Add to constrain',
handler: this.addConstrain
}];
this.callParent();
}

The proper way to design your class is like this. You apply your config settings to the object before you do the callParent.
Ext.define('EDS.view.selector.Container', {
extend: 'Ext.form.Panel',
alias : 'widget.selectorcontainer',
title: 'Selector_V2',
renderTo: 'input-div',
layout: 'fit',
height: '100%',
initComponent: function() {
Ext.applyIf(this, {
items: [
{
xtype: 'tabpanel',
defaults: {
bodyPadding: 10
}
}
],
buttons: [
{
text: 'Reset',
scope: this, // <--- scope to form panel
handler: function(){
console.log("Reset");
this.getForm().reset();
}
},
{
text: 'Add to constrain',
scope : this, // <--- scope to form panel
handler: this.addConstrain
}
]
});
this.callParent(arguments);
}
/*
* Logic for button "Add to constrain"
*
* Adds an entry into the constrain list describing a person, cost center or an application
*/
addConstrain: function(button, event){
console.log('Add_to_constrain clicked');
}
});

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

ExtJS 4.2 attach event in view to other views

I have a view with the following in my initComponent:
initComponent: function() {
var me = this;
Ext.applyIf(me, {
buttons: [
{
text: 'Guardar',
action: 'commit',
glyph: Glyphs.SAVE
}
],
items: [{
xtype: 'shiftpattern.window.formcode',
height: 50
},
{
xtype: 'shiftpattern.window.grid',
flex: 1
},
{
xtype: 'shiftpattern.window.formpattern',
height: 180
}
]
});
// here i need to listen to the grid's selectionchange event
me.on('selectionchange', me.onGridSelectionChange, me);
me.callParent(arguments);
},
onGridSelectionChange: function(grid, records) {
console.log('daysoff grid selection');
var me = this,
record = records[0];
}
I know that I can do that inside a controller, but in this case this view has it'w own behavior and I can reuse it in my sections of my application.
Is there a way to insert a selector to me.on('selectionchange', me.onGridSelectionChange, me);
Any clue on how to do that?
Just solved it:
me.on('selectionchange', me.onGridSelectionChange, me);
has to go after:
me.callParent(arguments);

How to get application from view?

How can I get my application from a view?
For example consider I have an application Boo and there's a view that named Boo.view.Foo.List and I want to get Boo in the view List.
Edit:
See this code, and look at the line 20.
Ext.define('Boo.view.Foo.List', {
extend: 'Ext.panel.Panel',
model: 'Boo.model.FooModel',
alias: 'widget.foolist',
store: 'FooListStore',
initComponent: function () {
this.columns = [
{
text: "Hello world",
dataIndex: 'Time',
flex: 1
},
{
xtype: 'actioncolumn',
width: 50,
items: [{
icon: 'cancel.png',
tooltip: 'Cancel',
handler: function (grid, rowIndex, colIndex, col, e) {
//Now I need to get the application here, for example with self.getApplication() or something like this.
}
}]
}];
this.callParent(arguments);
}
});
You can archieve this using the appProperty
Ext.application({
name: 'MyApp',
appProperty: 'Current'
});
You can now call
MyApp.Current
from anywhere cause the MyApp namespace resist within the window (global) scope.
For any Version before 4.1.3 add the following line to the Launch-Method of the Application
YourAppName[this.appProperty] = this;

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

Resources