Results 1 to 3 of 3

Thread: Changing hash before launch causes action to be called twice

    Thank you for reporting this bug. We will make it our priority to review this report.
  1. #1

    Default Changing hash before launch causes action to be called twice

    Example controller which attempts to change the hash before launch occurs and routing is called.

    Code:
    /**
     * The main application controller. This is a good place to handle things like routes.
     */
    Ext.define('app.controller.Root', {
        extend: 'Ext.app.Controller',
        requires: [
            'Ext.util.History'
        ],
    
    
        init: function() {
            var history = Ext.util.History,
                currentHash = history.getHash();
            if (app.model.Member.isLoggedIn()) {
                
            } else if (currentHash.indexOf('login') !== 0) {
                // Both of these result in a double call because of the hashchange event.
                // history.setHash('login/' + history.getHash());
                this.getApplication().redirectTo('login/' + history.getHash());
            }
        }
    });
    Fix for Ext.util.History.handleStateChange

    Code:
    /**
     *    Fix for handleStateChange to chekcing if the currentToken is different than token before proceeding.
     *    Added a 'force' property as well so that handleStateChange could still continue if 'force' === true.
     */
    Ext.define('app.util.History', {
        override: 'Ext.util.History',
        /**
         * Handles when the hash in the URL has been updated. Will also fired the change event.
         *
         * @param {String} token The token that was changed to
         * @private
         */
        handleStateChange: function(token, force) {
            if (this.currentToken !== token || force === true) {
                this.callParent(arguments);
            }
        }
    });

  2. #2
    Sencha Premium User mitchellsimoens's Avatar
    Join Date
    Mar 2007
    Location
    Gainesville, FL
    Posts
    40,379

    Default

    This is because in Ext.app.Application it triggers the Router to react to the current hash but you also are changing it so you are causing the reflow. Instead of how you are doing it, this is an example of how I would do user auth:

    Code:
    Ext.define('app.controller.Root', {
        extend : 'Ext.app.Controller',
    
        routes : {
            'login/:id' : 'onLogin',
            'blah'      : {
                action : 'onBlah',
                before : 'checkUser'
            }
        },
    
        checkUser : function() {
            var args   = Ext.Array.slice(arguments),
                action = args.pop();
    
            if (app.model.Member.isLoggedIn()) {
                action.resume();
            } else {
                action.stop(true);
    
                this.redirectTo('login/' + Ext.util.History.getHash());
            }
        },
    
        onBlah : function() {
            var body = Ext.getBody();
    
            body.update(body.getHtml() + '<div>blah</div>');
        },
    
        onLogin : function(id) {
            var body = Ext.getBody();
    
            body.update(body.getHtml() + '<div>login - ' + id + '</div>');
        }
    });
    Now if you go to http://example.com/#blah it will stop the route and any other routes in other controllers thanks to the action.stop(true) and then redirect to the login route. This will also work every time someone goes to the #blah hash and not just at application start as your way was insecure.
    Mitchell Simoens @LikelyMitch

    Check out my GitHub:
    https://github.com/mitchellsimoens

    Posts are my own, not any current, past or future employer's.

  3. #3
    Sencha User
    Join Date
    Sep 2007
    Posts
    3

    Default

    Sorry to bring this question to life again, but your solution, although effective, is for one route only. Now imagine doing that 'app wise', I mean, for ANY routes that enters the app I want to validate if the user is logged in. I'd have to write the before to all of them?

    Quote Originally Posted by mitchellsimoens View Post
    This is because in Ext.app.Application it triggers the Router to react to the current hash but you also are changing it so you are causing the reflow. Instead of how you are doing it, this is an example of how I would do user auth:

    Code:
    Ext.define('app.controller.Root', {
        extend : 'Ext.app.Controller',
    
        routes : {
            'login/:id' : 'onLogin',
            'blah'      : {
                action : 'onBlah',
                before : 'checkUser'
            }
        },
    
        checkUser : function() {
            var args   = Ext.Array.slice(arguments),
                action = args.pop();
    
            if (app.model.Member.isLoggedIn()) {
                action.resume();
            } else {
                action.stop(true);
    
                this.redirectTo('login/' + Ext.util.History.getHash());
            }
        },
    
        onBlah : function() {
            var body = Ext.getBody();
    
            body.update(body.getHtml() + '<div>blah</div>');
        },
    
        onLogin : function(id) {
            var body = Ext.getBody();
    
            body.update(body.getHtml() + '<div>login - ' + id + '</div>');
        }
    });
    Now if you go to http://example.com/#blah it will stop the route and any other routes in other controllers thanks to the action.stop(true) and then redirect to the login route. This will also work every time someone goes to the #blah hash and not just at application start as your way was insecure.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •