Sencha Architect 3.2. Why are buttons sending 2 click events? - events

I'm building a web based application using Extjs in Sencha architect. I've been building apps with this tool for nearly 7 years so I'm familiar with the tool and the architecture. But now, every button is sending 2 click events. I've added a simple button with the id 'testButton'
{
xtype: 'panel',
region: 'south',
id: 'KPIWindowStatusBarPanel',
margin: '0 5 5 5',
manageHeight: false,
dockedItems: [
{
xtype: 'toolbar',
dock: 'top',
items: [
{
xtype: 'tbfill'
},
{
xtype: 'button',
id: 'testButton',
itemId: 'testButton',
text: 'TestButton'
},
and so on
My controller is mapped normally
control: {
"#testButton": {
click: 'onTestButtonClick'
}
and so on
The actual function is just a console.log()
onTestButtonClick: function(button, e, eOpts) {
console.log('test button click');
},
But Firebug shows that this, and every other button is sending 2 click events every time they are pressed.
Does anyone have any idea why this is happening? I've never seen this before in any of our other apps.

There aren't any problems. You have to look somewhere else, maybe you double click?
Take a look on example on fiddle: https://fiddle.sencha.com/#view/editor&fiddle/356g
Ext.define('Fiddle.controller.ButtonController', {
extend: 'Ext.app.Controller',
control: {
"#testButton": {
click: 'onTestButtonClick'
}
},
onTestButtonClick: function (button, e, eOpts) {
console.log('test button click');
}
});
Ext.application({
name: 'Fiddle',
controllers: ['ButtonController'],
launch: function () {
Ext.create('Ext.panel.Panel', {
height: 200,
dockedItems: [{
xtype: 'toolbar',
dock: 'top',
items: [{
xtype: 'tbfill'
}, {
xtype: 'button',
id: 'testButton',
itemId: 'testButton',
text: 'TestButton'
}]
}],
width: 250,
renderTo: Ext.getBody()
});
}
});

This makes no sense, and I will add it to the list of reasons I should move away from Sencha Architect and ExtJS and over to Angular JS. I've lost count of how many times we've had impossible problems with an app built in Sencha Architect over the past 7 years.
I had 2 controllers. My main controller, and a 2nd controller called KPIController just to handle all the functions in this specific panel. I had a "loadData" function which loads data into a grid panel in the KPIControler. When I moved that method out of my KPIController and into the MainController all the buttons started sending single clicks again.
It makes no sense at all.

Related

ExtJS 5.1: Change the store of combobox on form 'boxready' event

I'm having a problem with performing any action on combobox's store on the form's boxready event or at any other event that occurs before the dialog is fully rendered (combobox's afterrender, etc.).
E.g. something like this.getCombobox().getStore().removeAll() works perfectly on any event firing up on the form, except the ones that happen initially during dialog/elements loading...
problem with performing any action on combobox's store on the form's
boxready event or at any other event that occurs before the dialog is
fully rendered (combobox's afterrender, etc.)
No problems at all:
Ext.widget({
xtype: 'form',
items: [
{
xtype: 'combo',
store: Ext.create('Ext.data.Store', {
fields: ['abbr', 'name'],
data : [
{"abbr":"AL", "name":"Alabama"},
{"abbr":"AK", "name":"Alaska"},
{"abbr":"AZ", "name":"Arizona"}
]
}),
fieldLabel: 'Choose State',
queryMode: 'local',
displayField: 'name',
valueField: 'abbr',
listeners: {
'afterrender': function() {
console.log("combo's afterrender");
}
}
}
],
renderTo: Ext.getBody(),
listeners: {
'boxready': function() {
console.log("form's boxready");
this.down('combo').getStore().setData([
{"abbr":"ME", "name":"Middle Earth"}
]);
},
'afterrender': function() {
console.log("form's afterrender");
}
}
});
By the way, as you can see in the fiddle, boxready happens after afterrender, not before.

ExtJS 4: Ext.grid.Panel using Edit plugin calls "selectionchange" event twice when clicked if grid is a nested component

Below is the event that is fired after a row is selected in an Ext.grid.Panel component. I have a form with a grid inside of it as one of the items (child component). The grid is being added using the xtype of the nested Ext.grid.Panel component. For some reason, when I click a row in this nested grid component within the form, this event gets called twice. It appears that it selects it, then the grid refreshes (it goes completely white/blank), and then it re-renders. In a typical implementation of this exact same grid (not nested), this event only gets called once.
Two questions. (1) How do I fix this in the short term? (2) How would I troubleshoot this to find the cause?
Event in controller:
'view-attribute-grid': {
selectionchange: function (selModel, selected) {
alert('selectionchange event called');
}
}
Grid looks almost identical to this implementation, with a few minor changes:
http://demo.rasc.ch/eds/extjs42/rowedit.html?theme=classic
EDIT:
Nesting:
.. see xtype: 'view-attribute-grid', below ...
Ext.define('App.view.TestForm', {
extend: 'Ext.form.Panel',
xtype: 'view-test-form',
requires: [
'Ext.form.field.Text',
'App.store.TestForm'
],
initComponent: function () {
this.addEvents('create');
Ext.apply(this, {
activeRecord: null,
frame: true,
defaultType: 'textfield',
bodyPadding: 5,
fieldDefaults: {
anchor: '100%',
labelAlign: 'right'
},
items: [{
fieldLabel: 'ID',
name: 'form_id',
allowBlank: false,
disabled: true
}, {
xtype: 'view-attribute-grid',
itemId: Ext.id()
}],
dockedItems: [{
xtype: 'toolbar',
dock: 'bottom',
ui: 'footer',
...

activate/deactivate config listeners not firing in navigationview to hide navigationbar button in sencha touch 2

I am attempting to do something which (at least I believe) should be very straightforward in ST2 but it is not working. I have a main view (xtype: navigationview) and a secondary view (xtype: container). There is a button in the navigationbar on the main view that should be hidden when navigating to the secondary view and shown when returning to the main view. I have added the code to mark the setHidden(true) in the main view config listeners but neither of the events fire.
Is there maybe a better way of doing this?
Main view:
Ext.define('MyApp.view.Main', {
extend: 'Ext.navigation.View',
xtype: 'main',
requires: [
'Ext.dataview.List'
],
config: {
navigationBar: {
items: [
{
xtype: 'button',
iconCls: 'refresh',
iconMask: true,
itemId: 'refreshBtn',
align: 'left'
}
]
},
items: [
{
xtype: 'button',
itemId: 'next-page-button',
text: 'Next Page'
}
],
listeners: {
activate: function() {
this.query('[itemId=refrehBtn]')[0].setHidden(false);
},
deactivate: function() {
this.query('[itemId=refrehBtn]')[0].setHidden(true);
}
}
},
initialize: function() {
this.callParent();
}
});
Sencondary view:
Ext.define('MyApp.view.Main2', {
extend: 'Ext.Container',
xtype: 'main2',
config: {
items: [
{
xtype: 'panel',
items: [
{
xtype: 'panel',
html: 'second view'
},
]
}
]
}
});
Controller:
Ext.define('MyApp.controller.TestController', {
extend: 'Ext.app.Controller',
config: {
refs: {
nextPgBtn: '[itemId=next-page-button]'
},
control: {
nextPgBtn: {
tap: 'showNextPg'
}
}
},
showNextPg: function(btn, e, opts) {
btn.up('navigationview').push({
xtype: 'main2'
});
}
});
Firstly, you need to change your query to correctly retrieve your button. Change this:
this.query('[itemId=refrehBtn]')[0].setHidden(false);
to this:
Ext.ComponentQuery.query('#refreshBtn')[0].setHidden(false);
Secondly, instead of using activate and deactivate event, you should make use of back
event which fires when the back button in the navigation view was tapped. and push event which fires when a view is pushed into this navigation view in order to show and hide your button accordingly:
back: function() {
Ext.ComponentQuery.query('#refreshBtn')[0].setHidden(false);
},
push: function() {
Ext.ComponentQuery.query('#refreshBtn')[0].setHidden(true);
}
Here is a demo: http://www.senchafiddle.com/#GSt6x

MVC Sencha Touch Won't Properly Display Tab Panels

I have a MVC Sencha Touch application I'm building and am having some issues getting the TabPanel to function correctly. The issue is this, when I have my PosViewport.js like this, everything works fine:
touch.views.PosViewport = new Ext.extend(Ext.TabPanel, {
initComponent: function () {
console.log("inside initComponent() of PosViewport.js");
touch.views.PosViewport.superclass.initComponent.call(this);
},
tabBar: {
dock: 'bottom',
layout: {
pack: 'center'
}
},
layout: 'fit',
scroll: 'vertical',
items: [
{
title: 'Reciepts',
iconCls: 'bookmarks',
html: 'one'
},
{
title: 'POS',
iconCls: 'Favorites',
html: 'two'
}
]
});
Here, everything is great! The tab bar shows up on the bottom, it fits perfectly, and I can switch back and forth between the two with no problems.
However, instead of keeping those panels inside my PosViewport.js file, let's move them out to two seperate files:
View1.js:
touch.views.View1 = new Ext.extend(Ext.Panel, {
initComponent: function () {
touch.views.View1.superclass.initComponent.call(this);
},
layout: 'fit',
scroll: 'vertical',
fullscreen : true,
title: 'Reciepts',
iconCls: 'bookmarks',
html: 'panel one'
});
and View2.js:
touch.views.View2 = new Ext.extend(Ext.Panel, {
initComponent: function () {
touch.views.View2.superclass.initComponent.call(this);
},
layout: 'fit',
scroll: 'vertical',
fullscreen : true,
title: '2',
iconCls: 'bookmarks',
html: 'panel two'
});
I add both new views to my index.html. Now, I update my PosViewport.js to point to the new views:
touch.views.PosViewport = new Ext.extend(Ext.TabPanel, {
initComponent: function () {
console.log("inside initComponent() of PosViewport.js");
touch.views.PosViewport.superclass.initComponent.call(this);
},
tabBar: {
dock: 'bottom',
layout: {
pack: 'center'
}
},
layout: 'fit',
scroll: 'vertical',
items: [ touch.views.View1, touch.views.View2]
});
And it all goes to hell. The Bottom Tab Bar is not visible, as only a tiny piece of the top is visible on the page. The panels do not show up at all, I cannot see their HTML content at all.
What is going on here? I have absolutely no idea why it is behaving like this. Any pointers in the right direction are much appreciated, thank you!
In the second case you created two classes by this:
touch.views.View2 = new Ext.extend(Ext.Panel, { // Class definition
whereas you needed two instances of these panels. So, add the items like this:
items: [new touch.views.View1(), new touch.views.View2()] // Panel instance
This should work now. And remove the fullscreen:true option from these panels. fullscreen means, it will make the panels take whole viewport area.

Sencha Touch Swap Panels

I just started using sencha touch recently and so far I've got this built:
app.js:
Ext.regApplication({
name: 'app',
launch: function() {
this.launched = true;
this.mainLaunch();
},
mainLaunch: function() {
if (!device || !this.launched) {return;}
this.views.viewport = new this.views.Viewport();
}
});
Viewport.js:
app = Ext.extend(Ext.TabPanel, {
fullscreen: true,
sortable: false,
tabBar: {
dock: 'bottom',
layout: {pack: 'center'}
},
cardSwitchAnimation: {
type: 'slide',
cover: true
},
initComponent: function() {
Ext.apply(app.views, {
searchListTab: new app.views.SearchListTab(),
searchTab: new app.views.SearchTab(),
mapTab: new app.views.MapTab(),
infoTab: new app.views.InfoTab()
});
Ext.apply(this, {
items: [
app.views.searchTab,
app.views.mapTab,
app.views.infoTab
]
});
app.views.Viewport.superclass.initComponent.apply(this, arguments);
}
});
SearchTab.js
app.views.SearchTab = Ext.extend(Ext.Panel, {
title: 'Search',
iconCls: 'search',
dockedItems: [{
xtype: 'toolbar',
title: 'Search'
}],
items: [
{
xtype: 'button',
ui: 'round',
text: 'Hledej',
listeners: {
tap: function() {
Ext.dispatch({
controller: app.controllers.main,
action: 'search',
animation: {type:'slide', direction:'right'}
});
}
}
}
],
initComponent: function() {
app.views.SearchTab.superclass.initComponent.apply(this, arguments);
}
});
SearchListTab.js
app.views.SearchListTab = Ext.extend(Ext.Panel, {
title: 'Search',
iconCls: 'search',
dockedItems: [{
xtype: 'toolbar',
title: 'Search Results'
}],
items: [{
xtype: 'list',
store: app.stores.results,
itemTpl: '{titul}',
grouped: false
//onItemDisclosure: function (record) {
//Ext.dispatch({
// controller: app.controllers.contacts,
// action: 'show',
// id: record.getId()
//});
//}
}],
initComponent: function() {
app.stores.results.load();
app.views.SearchListTab.superclass.initComponent.apply(this, arguments);
}
});
and search.js
app.controllers.main = new Ext.Controller({
search: function(options) {
app.views.searchTab.setActiveItem(
app.views.searchListTab, options.animation
);
}
});
and some other stuff which is not important now. So basically I've got a main viewport which is a tabpanel, then few panels which are its items and one panel which is nowhere from the beginning. Now I want to achieve, that when I click the button in searchTab I want the searchTab panel to swap with searchListTab panel. The problem is, when I use app.views.viewport.setActiveItem(...); it works fine, but it adds a new tab to the tab panel. I just want the current tab panel to slide to another panel, but when I use the code I posted here - app.views.searchTab.setActiveItem(...); it doesn't do anything.
What am I doing wrong? Thanks.
I think you will have to introduce another layer of nesting to achieve this.
I think you want to nest your SearchTab in another Ext.Panel with a card layout and add your SearchListTab to this panel when needed and then you can use the setActiveItem() method to slide across. This will keep your TabPanel visible while moving between sub-views within a tab.
I've drawn a wee diagram to try and explain it better! The black box is the new Panel I think you should add which will replace the SearchTab as the item directly added to the TabPanel.
Hope this helps and is clear!

Resources