1. #1
    Sencha User
    Join Date
    Oct 2012
    Posts
    27
    Answers
    2
    Vote Rating
    1
    English is on a distinguished road

      0  

    Default Unanswered: Button handler event not calling function (not firing)

    Unanswered: Button handler event not calling function (not firing)


    I have a view defined, which contains a form panel, which contains a button.
    I have set the "handler" to a function within the class, but it just does not fire.
    If I put an inline function into the "handler" declaration, then it works.

    I'd sure appreciate some advice!

    Code:
    Ext.define("lmsmobile.view.Login", {    extend: 'Ext.form.Panel',
        alias: 'widget.LoginForm',
        initialize: function(){
            this.callParent();
            console.log("Initialising the Login view");
        },
        requires: [
            'Ext.Toolbar',
              'Ext.Img',
              'Ext.form.FieldSet',
              'Ext.form.Password',
              'Ext.Button'
        ],
        config: {
             url: 'CheckLogin.php',
            baseCls: 'MainPanel',
            items: [
                {
                    xtype: 'image',
                    src: 'resources/images/logo.png',
                    width: 492,
                    height: 90
                },
                {
                    xtype: 'fieldset',
                    title: 'User Login',
                    instructions: 'Please enter your username and password.',
                    items: [
                        {
                            xtype: 'textfield',
                            name: 'txtUserName',
                            label: 'User Name:',
                            placeHolder: 'Enter your User Name',
                            required: true
                        },
                        {
                            xtype: 'passwordfield',
                            name: 'txtPassword',
                            label: 'Password:',
                            placeHolder: 'Enter your password',
                            required: true
                        }
                    ]
                },
                {
                    xtype: 'button',
                    text: 'Login',
                    ui: 'action',
                    id: 'LoginButton',
                    handler: this.onLoginButtonPress,
                    scope: this,
                },
                {
                    xtype: 'button',
                    text: 'Forgot Password'
                },
                {
                    xtype: 'button',
                    text: 'Contact Support'
                },
                {
                    docked: 'bottom',
                    xtype: 'toolbar',
                    title: 'Testing',
                },
            ]
        },
        onLoginButtonPress: function() {
            console.log("onLoginButtonPress from the view.");
            //this.fireEvent("LoginButtonPressed", this);
        }
    });

  2. #2
    Sencha User
    Join Date
    Apr 2010
    Location
    China
    Posts
    227
    Answers
    64
    Vote Rating
    20
    haduki will become famous soon enough haduki will become famous soon enough

      0  

    Default


    'this' is window object.
    Code:
    var config={
        test:this,
        buttonConfig:{
            test:this
        }
    }
    console.info(config.test);
    console.info(config.buttonConfig.test);
    Code:
    config:{
        listeners:{
            initialize:function(){
    
                this.down('#LoginButton').setHandler(this.onLoginButtonPress);
                this.down('#LoginButton').setScope(this);
            }
        }
    }
    I write English by translator.

  3. #3
    Sencha User
    Join Date
    Oct 2012
    Posts
    27
    Answers
    2
    Vote Rating
    1
    English is on a distinguished road

      0  

    Default


    Thanks. I understand that "this" in that context refers to the window object. However, I have tried all ways, with, or without. That was just defaulted back to the sample code that I was using as an outline.

    Whatever I do, the "handler:" does nothing. I was interested in the handler: use, not adding listeners - although I tried that with no success also.

    I would appreciate something more specific to the code I posted, if possible.

  4. #4
    Sencha User
    Join Date
    Apr 2010
    Location
    China
    Posts
    227
    Answers
    64
    Vote Rating
    20
    haduki will become famous soon enough haduki will become famous soon enough

      0  

    Default


    Code:
    Ext.define("lmsmobile.view.Login", {    extend: 'Ext.form.Panel',
        alias: 'widget.LoginForm',
        initialize: function(){
            this.callParent();
            console.log("Initialising the Login view");
            /*
              you can write here as well
            this.down('#LoginButton').setHandler(this.onLoginButtonPress);
            this.down('#LoginButton').setScope(this);
            */
    
        },
        requires: [
            'Ext.Toolbar',
              'Ext.Img',
              'Ext.form.FieldSet',
              'Ext.form.Password',
              'Ext.Button'
        ],
        config: {
             url: 'CheckLogin.php',
            baseCls: 'MainPanel',
            items: [
                {
                    xtype: 'image',
                    src: 'resources/images/logo.png',
                    width: 492,
                    height: 90
                },
                {
                    xtype: 'fieldset',
                    title: 'User Login',
                    instructions: 'Please enter your username and password.',
                    items: [
                        {
                            xtype: 'textfield',
                            name: 'txtUserName',
                            label: 'User Name:',
                            placeHolder: 'Enter your User Name',
                            required: true
                        },
                        {
                            xtype: 'passwordfield',
                            name: 'txtPassword',
                            label: 'Password:',
                            placeHolder: 'Enter your password',
                            required: true
                        }
                    ]
                },
                {
                    xtype: 'button',
                    text: 'Login',
                    ui: 'action',
                    id: 'LoginButton'
                    //,handler: this.onLoginButtonPress,
                    //scope: this,
                },
                {
                    xtype: 'button',
                    text: 'Forgot Password'
                },
                {
                    xtype: 'button',
                    text: 'Contact Support'
                },
                {
                    docked: 'bottom',
                    xtype: 'toolbar',
                    title: 'Testing',
                }
            ],
    		listeners:{
                initialize:function(){
    
    
                    this.down('#LoginButton').setHandler(this.onLoginButtonPress);
                    this.down('#LoginButton').setScope(this);
                }
            }
        },
        onLoginButtonPress: function() {
            console.log("onLoginButtonPress from the view.");
            //this.fireEvent("LoginButtonPressed", this);
        }
    });
    I write English by translator.

  5. #5
    Sencha User
    Join Date
    Oct 2012
    Posts
    27
    Answers
    2
    Vote Rating
    1
    English is on a distinguished road

      0  

    Default


    Thanks, Haduki. So, from the fact that you're always using the "listeners", do I understand that I can't use the "handler" configuration at all?

    I like the idea of setting the handler, and this is intending to raise an event which will be intercepted by a controller.

  6. #6
    Sencha User
    Join Date
    Apr 2010
    Location
    China
    Posts
    227
    Answers
    64
    Vote Rating
    20
    haduki will become famous soon enough haduki will become famous soon enough

      0  

    Default


    You are able to use hanlder configuration if you can pass the scope(not the scope configuration) correctly .
    example:
    Code:
    Ext.application({
        launch:function(){
             var view=Ext.getCmp('someViewId');
             var button= Ext.create('Ext.Button',{
                     handler:view.OnButtonTap,
                     scope:view
             });
             view.add(button);
        }
    })
    Code:
    Ext.define("lmsmobile.view.Login", {    extend: 'Ext.form.Panel',
        alias: 'widget.LoginForm',
        initialize: function(){//<--not listener
            this.callParent();
            console.log("Initialising the Login view");
            this.insert(2,{
                    xtype: 'button',
                    text: 'Login',
                    ui: 'action',
                    id: 'LoginButton'
                    ,handler: this.onLoginButtonPress,//<-- here ,'this' is your LoginForm instance ,not 'window'
                    scope: this,
                });
    
            
    
        },
        config:{
            items:[
                {/*image*/},
                {/*fieldset*/},
                 //<--insert login button here
                {/*button forgot password*/},
                ...
           ]
        }
      ...
    I write English by translator.

  7. #7
    Sencha - Senior Forum Manager mitchellsimoens's Avatar
    Join Date
    Mar 2007
    Location
    Gainesville, FL
    Posts
    36,522
    Answers
    3447
    Vote Rating
    814
    mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute

      0  

    Default


    From this config from OP:

    Code:
                {
                    xtype: 'button',
                    text: 'Login',
                    ui: 'action',
                    id: 'LoginButton',
                    handler: this.onLoginButtonPress,
                    scope: this,
                },
    this is of the window so it's not going to be able to find onLoginButtonPress on the lmsmobile.view.Login component.

    I would use the control config to listen for the tap event on that button:

    Code:
    config : {
        control : {
            '#LoginButton' : 'onLoginButtonPress'
        }
    }
    Mitchell Simoens @SenchaMitch
    Sencha Inc, Senior Forum Manager
    ________________
    Check out my GitHub, lots of nice things for Ext JS 4 and Sencha Touch 2
    https://github.com/mitchellsimoens

    Think my support is good? Get more personalized support via a support subscription. https://www.sencha.com/store/

    Need more help with your app? Hire Sencha Services services@sencha.com

    Want to learn Sencha Touch 2? Check out Sencha Touch in Action that is in print!

    When posting code, please use BBCode's CODE tags.

  8. #8
    Sencha User Kikketer's Avatar
    Join Date
    Apr 2012
    Location
    Wausau, WI
    Posts
    135
    Answers
    6
    Vote Rating
    7
    Kikketer is on a distinguished road

      0  

    Default


    So in the config for views, the "this" variable is the window. From what I understand, the config is an object passed to the constructor functions of whatever you are extending. Couldn't these constructor functions realize that "this" should probably be the view you are creating and not window (.apply or .call)?

    From what I've gathered above, there are several ways to listen to a button press. For me, the way that makes sense is to add the handler since you have one place to see all the attributes of the button and the handler for it. Unlike the listener and control options, that require you to look in other random places for these functions.

    I was able to get this to work:
    {
    xtype: "button",
    ui: "back",
    text: "Home",
    handler: function() { console.log("yay"); },
    scope: this
    },
    But of course that's not ideal either. To me it seems that if the handler isn't providing any use, which it isn't (and only encuraging messy config objects) it should be removed.

  9. #9
    Sencha User
    Join Date
    Feb 2011
    Location
    Düsseldorf, Germany
    Posts
    567
    Answers
    34
    Vote Rating
    31
    Kurt001 has a spectacular aura about Kurt001 has a spectacular aura about

      0  

    Default


    How about following some MVC?

    View
    Code:
    Ext.define("lmsmobile.view.Login", {
        extend: 'Ext.form.Panel',
        xtype: 'loginform', 
        config: {
            items: [
                {
                    xtype: 'button',
                    text: 'Login',
                    ui: 'action',
                    itemId: 'loginButton'
                }
            ]
        }
    });
    Controller
    Code:
    Ext.define('lmsmobile.controller.Login', {
        extend: 'Ext.app.Controller',
    
        config: {
            refs: {
                 btnLogin: '.loginform #loginButton'
            },
            control: {
                btnLogin: { tap: 'onBtnLoginTap' }
            }
        },
    
        onBtnLoginTap: function (btn) {
            console.log("onLoginButtonPress from the view.");
        }
    });

  10. #10
    Sencha User Kikketer's Avatar
    Join Date
    Apr 2012
    Location
    Wausau, WI
    Posts
    135
    Answers
    6
    Vote Rating
    7
    Kikketer is on a distinguished road

      0  

    Default


    MVC makes sense, and I guess it's all in the eye of the beholder. But to me the code you posted above is more of a "view-controller" since the controller is closely linked to the view (selecting a specific button with this specific id on the view). Ideally the controller would listen for simple events that the view is emitting, that way the view can do whatever it wants (even remove the button) as long as it still emits the event.

    Basically a contract between the controller and the view, allowing flexibility on both sides using events.

    I've decided to use the "control" keyword, as it's very similar to BackboneJS that I've been using for some time now. The control in the view would simply call a function that would emit an event that the controller is listening to. This also gives deeper control as to what you hand over to the controller, instead of the standard arguments that are sent with a tap event.