简体   繁体   English

带有ui.router $ state的AngularJS在异步时不起作用

[英]AngularJS with ui.router $state not working when async

I have a problem with the use of AngularJS and ui.router . 我在使用AngularJSui.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 : 我的问题是,通过使用异步系统,我无法更改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/ 代码: http//jsfiddle.net/dievardump/x2tMT/

demo full : http://jsfiddle.net/dievardump/x2tMT/embedded/result/ 完整的演示: http : //jsfiddle.net/dievardump/x2tMT/embedded/result/

This one is the one that is not ok (see console). 这是一个不正确的选项(请参阅控制台)。

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

demo full : http://jsfiddle.net/dievardump/f9rSQ/embedded/result/ 完整的演示: http : //jsfiddle.net/dievardump/f9rSQ/embedded/result/

The ONLY difference between these two samples is in the declaration of the state "platform.channels" : 这两个示例之间唯一的区别是在状态“ platform.channels”的声明中:

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

VS 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 ? $ state.go在setTimeout中不起作用的任何原因?

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. angular提供$timeout服务。

read more on that here : https://docs.angularjs.org/api/ng/service/ $timeout 在此处阅读更多信息: https : //docs.angularjs.org/api/ng/service/ $ timeout

working (fixed Async demo here) : http://jsfiddle.net/f9rSQ/2/ 工作(此处已修复了异步演示): 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. PS,您应该始终使用angular的方式或ng- *指令来处理异步更改,如果您通过纯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. 为了使它们开火,您可以强制angular运行$digest循环,这是在使用ng-click$http等时以更清洁的方式实际发生的情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM