PDA

View Full Version : MVC and Button events



slchorne
20 Oct 2011, 11:10 AM
I'm trying to wrap my head around MVC, but I can't seem to get a simple button handler event to work. I've defined a simple panel with a single button. But when i click/tap on the button, the event doesn't fire.

What am I missing ? I've defined the panel here


Ext.application({
name: 'myApp',

// register any relevant controllers, ([ ] why).
// these are relative to the app's 'name' so the full
// name when you extend Ext.app.Controller should be
// 'myApp.controller.myC'
controllers: [ 'myC' ],

// the 'launch' handler is called when ALL the .js files have loaded
launch: function() {

console.log( 'launch' , myApp );

// create the main panel
var p = Ext.create('Ext.Panel',{
title: 'test',
layout: 'hbox',
items: [
{
xtype: 'button',
itemId: 'mybutton',
text: "click me",
}
]
});
// Add and render the main panel
Ext.Viewport.add( p );
}

});



Then define the handler here


Ext.define('myApp.controller.myC', {
extend: 'Ext.app.Controller',

init: function() {

console.log( 'init control' , myApp );

// try and find something
var A = Ext.ComponentQuery.query('#mybutton');
console.log ( "q: " , A );


this.control({
'#mybutton':{
itemtap: this.clickHandler
},
});
},
clickHandler: function(){
console.log('it was clicked');
}
});


Also, can someone explain why i need the 'controllers' config to register the controller. This seems messy if i rename the controller. Is there a way to 'auto register' controllers.

olouvignes
20 Oct 2011, 4:24 PM
Check out "refs" : http://docs.sencha.com/touch/2-0/#!/api/Ext.app.Controller

slchorne
20 Oct 2011, 4:43 PM
I'm not sure what you mean. 'refs' are just shortcuts to let you get to the object via a different namespace. But they only are useful when you are in the actual even handler. And '#mybutton' should give me a ref directly to that button anyway. ( I know this because 'Ext.ComponentQuery.query('#mybutton'); " returns the button I want to listen to).

So I could do this


refs: [ {
ref: 'buttons',
selector: '#mybutton'
} ],

And then get to that component via getButtons()

But the problem here is that 'clickHandler' is not even being called. 'this.control' is not being parsed correctly.

joseph09
20 Oct 2011, 8:55 PM
Try changing itemtap to tap in this.control





Ext.define('myApp.controller.myC', {
extend: 'Ext.app.Controller',

init: function() {

console.log( 'init control' , myApp );

// try and find something
var A = Ext.ComponentQuery.query('#mybutton');
console.log ( "q: " , A );


this.control({
'#mybutton':{
tap: this.clickHandler
},
});
},
clickHandler: function(){
console.log('it was clicked');
}
});

slchorne
21 Oct 2011, 9:11 AM
I tried both 'tap' and 'itemtap' (the jury is still out on which one is correct, if you read the threads) and neither of them work.

If I add a listener directly to the button, it does work, but this is an exercise in getting to understand the MVC model



xtype: 'button',
itemId: 'mybutton',
ui: 'decline',
text: "click me",
listeners: {
tap: function() {
console.log ( 'clicked tap' ) ;
}
}

oddz
21 Oct 2011, 9:26 AM
I believe this is related to this bug (http://www.sencha.com/forum/showthread.php?150940-Button-loosing-listener-if-another-button-is-created-after-it).

Unless buttons are added in the initialization phase events do not seem to occur.

slchorne
21 Oct 2011, 9:32 AM
That would also explain this bug:

http://www.sencha.com/forum/showthread.php?151639-multiple-toolbars-and-buttons-kill-events&p=662973#post662973

joseph09
21 Oct 2011, 9:42 AM
Try putting the button inside of a view and using a ref to it

slchorne
21 Oct 2011, 10:47 AM
I'm not sure what you mean (this is where my MVC education grinds to a halt).
Can you provide an example ?

joseph09
21 Oct 2011, 11:44 AM
No problem, I am just learning as well -

Instead of placing the button in the launch handler of app.js place it in a view

app.js



Ext.Loader.setConfig({ enabled: true });
Ext.application({
name: 'MyApp',
controllers: ['myC']
});




app/controller/Main.js


Ext.define('myApp.controller.myC', {
extend: 'Ext.app.Controller',

config: {
profile: Ext.os.deviceType.toLowerCase()
},

views : [
'Main'
],

stores: ['myStore'],

refs: [{
ref: 'main',
selector: 'mainview',
autoCreate: true,
xtype: 'mainview'
}, {
ref: 'myButton',
selector: '#myButton'
}, {
ref: 'myList',
selector: 'mylist'
}
],

init: function() {
this.getMainView().create();
this.control({
'#myButton': {
tap: this.onButtonTap
}
});
},

onButtonTap: function() {
//mainView = this.getMain();
//myList = this.getMyList();
//mainView.setActiveItem(myList);
console.log('Button Clicked!');
},
});





app/view/Main.js



Ext.define('myApp.view.Main', {
extend: 'Ext.Panel',
id: 'mainView',
requires: [
'Ext.Toolbar',
'Ext.Button'
],
config: {
fullscreen: true,

layout: {
type: 'card',
animation: {
type: 'slide',
direction: 'left',
duration: 250
}
},

items: [{
xtype: 'toolbar',
id: 'topToolbar',
docked: 'top',
items: [{
xtype: 'button',
text: 'My Button',
iconCls: 'home',
iconMask: true,
labelCls: 'button_label',
id: 'myButton'
}]
}]
}
});



The above code is rough and probably has errors but is meant to illustrate the point of placing the button in the view.

A couple of recommendations would be to use camelCaps (for example myButton instead of mybutton)
and to use id: 'myButton' instead of itemId: 'myButton'