Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I have a problem with the use of AngularJS and ui.router.

I have an application where basically a user write informations, which are send to the server, and when the server answer I change the current state to be a list of channels.

My problem is that by using an asynchroneus system I lose the ability to change the current state, without any error, demos :

The following demo is the one that is OK, because it does not use an asynchroneus system (see console):

code : http://jsfiddle.net/dievardump/x2tMT/

demo full : http://jsfiddle.net/dievardump/x2tMT/embedded/result/

This one is the one that is not ok (see console).

code : http://jsfiddle.net/dievardump/f9rSQ/

demo full : http://jsfiddle.net/dievardump/f9rSQ/embedded/result/

The ONLY difference between these two samples is in the declaration of the state "platform.channels" :

console.log('goes to platform.game'); $state.go('platform.game', { type: 'gameType', id: 1 });

VS

setTimeout(function () { console.log('should go to platform.game'); $state.go('platform.game', { type: 'gameType', id: 1 }); }, 1000);

Full demos easy to import locally :

Working :

<div ui-view></div>
<script>


var myApp = angular.module('myApp', ['ui.router']);
myApp.config(function($stateProvider, $urlRouterProvider) {
        $urlRouterProvider.otherwise("/signin");

        $stateProvider
            .state('platform', {
                url: '/platform',
                data: {
                    permissions: ['auth']
                },
                template: "<section class='platform'>platform<div ui-view></div></section>",
                controller: function($state) {
                    console.log('platformController');
                }
            });
});

myApp.config(function($stateProvider, $urlRouterProvider) {
    $stateProvider
        .state('signin', {
            url: "/signin",
            template: "<section id='connect' class='connect'><form name='connection' action='' ng-submit='login(connection)'><input placeholder='Choose a nickname' ng-model='nickname' autocomplete='off' /><button><span>Send</span></button></form><p class='error' ng-show='error != null'>{{error}}</p></section>",
            controller: function($scope, $state) {
                $scope.error = null;
                $scope.nickname = null;

                $scope.login = function(form) {
                    var value = $scope.nickname.replace(/[^a-zA-Z0-9]/g, '');
                    if (value.length >= 3) {
                        $state.go('platform.channels');
                    } else {
                        $scope.error = 'only characters and numbers. length must be >= 3';
                    }
                }
            }
        });
});

myApp.config(function($stateProvider, $urlRouterProvider) {

    $stateProvider.state('platform.channels', {
        url: "/channels",
        template: "<section id='channels' class='channels'>channels</section>",
        controller: function($state) {
            console.log('channelController');
            console.log('goes to platform.game');
            $state.go('platform.game', {
                type: 'gameType',
                id: 1
            });
        }
    })
});

myApp.config(function($stateProvider, $urlRouterProvider) {
    $stateProvider.state('platform.game', {
            url: "/game/:type/:id",
            template: "<section id='game' class='game'>game</section>",
            controller: function() {
                console.log('gameController');
            }
        });
});


angular.bootstrap(document, ['myApp']);
</script>

Non working :

<div ui-view></div>
<script>


var myApp = angular.module('myApp', ['ui.router']);
myApp.config(function($stateProvider, $urlRouterProvider) {
        $urlRouterProvider.otherwise("/signin");

        $stateProvider
            .state('platform', {
                url: '/platform',
                data: {
                    permissions: ['auth']
                },
                template: "<section class='platform'>platform<div ui-view></div></section>",
                controller: function($state) {
                    console.log('platformController');
                }
            });
});

myApp.config(function($stateProvider, $urlRouterProvider) {
    $stateProvider
        .state('signin', {
            url: "/signin",
            template: "<section id='connect' class='connect'><form name='connection' action='' ng-submit='login(connection)'><input placeholder='Choose a nickname' ng-model='nickname' autocomplete='off' /><button><span>Send</span></button></form><p class='error' ng-show='error != null'>{{error}}</p></section>",
            controller: function($scope, $state) {
                $scope.error = null;
                $scope.nickname = null;

                $scope.login = function(form) {
                    var value = $scope.nickname.replace(/[^a-zA-Z0-9]/g, '');
                    if (value.length >= 3) {
                        $state.go('platform.channels');
                    } else {
                        $scope.error = 'only characters and numbers. length must be >= 3';
                    }
                }
            }
        });
});

myApp.config(function($stateProvider, $urlRouterProvider) {

    $stateProvider.state('platform.channels', {
        url: "/channels",
        template: "<section id='channels' class='channels'>channels</section>",
        controller: function($state) {
            console.log('channelController');
            setTimeout(function () {
                console.log('should go to platform.game');
                $state.go('platform.game', {
                    type: 'gameType',
                    id: 1
                });
            }, 1000);
        }
    })
});

myApp.config(function($stateProvider, $urlRouterProvider) {
    $stateProvider.state('platform.game', {
            url: "/game/:type/:id",
            template: "<section id='game' class='game'>game</section>",
            controller: function() {
                console.log('gameController');
            }
        });
});


angular.bootstrap(document, ['myApp']);
</script>

Any reason why $state.go does not work in the setTimeout ?

share|improve this question

1 Answer 1

up vote 2 down vote accepted

The reason why your demo does not work is the timeout, its simple when you cause a change out of angulars knowledge, angular stays un-aware of the changes happening and hence it wont update.

The solution is to use the angular way of doing this. angular provides $timeout service.

read more on that here : https://docs.angularjs.org/api/ng/service/$timeout

working (fixed Async demo here) : http://jsfiddle.net/f9rSQ/2/

PS you should always use angular's way or ng-* directives to handle asynchronous changes things like button click event listeners won't fire if you do them via pure javascript. To make them fire you can force angular to run a $digest cycle which is what actually happens in a cleaner way when you use ng-click , $http etc.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.