ui-router $state.go() to sibling using onEnter

by Olivier Peaucelle

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.15/angular-ui-router.js"></script>
<p>In this jsfiddle state "root.app.pivot" is landing page that redirects to 
    root.app.a or root.app.b
</p>
<p>When can see that the first time, "root" and "root.app" revolve method are triggered twice</p>
<p>and that when clicking on "page b" link a <span class="error">Error: null is not an object (evaluating '$state.$current.locals[name]')</span> occurs
</p>
<hr />
<div ng-app="myApp">
    <a ui-sref="root.app.pivot({page:'a'})">page a</a>&nbsp;|
    <a ui-sref="root.app.pivot({page:'b'})">page b</a>
    <ui-view name="main"></ui-view>
</div>

CSS

.error {
    color: red;
}
p {
    margin: 0;
    padding: 0;
}

JavaScript

angular.module('myApp', ['ui.router'])
    .config(['$stateProvider', '$urlRouterProvider',
        function ($stateProvider, $urlRouterProvider) {
            $urlRouterProvider.otherwise("/?page=a");
            $stateProvider
                .state('root', {
                    abstract: true,
                    views: {
                        'main': {
                            template:  '<ui-view name="body"></ui-view><hr />' +
                            'ResolveNames : <li ng-repeat="resolveName in resolveNames track by $index">{{ resolveName }}</li>'
                        }
                    },
                    resolve: {
                        foo: function($rootScope) {
                            if (! $rootScope.resolveNames) {
                                $rootScope.resolveNames = ['root'];
                            } else {
                                $rootScope.resolveNames.push('root');
                            }
                        }
                    }
                })
                .state('root.app', {
                    params: {
                        page: null
                    },
                    resolve: {
                        appData: function($q, $rootScope, $stateParams, $timeout) {
                            $rootScope.resolveNames.push('root.app');
                            var defer = $q.defer();
                            $timeout(function() {
                                defer.resolve({target: "root.app." + $stateParams.page});
                            }, 100);
                            return defer.promise;
                        }
                    }
                })
                .state('root.app.pivot', {
                    url: '^/?page',
                    views: {
                        'body@root': {
                            template: '<div>default body</div>'
                        }
                    },
                    onEnter: function($state,...