AngularJS $ location不更改路径


126

提交表单后,更改页面的URL时遇到问题。

这是我的应用程序的流程:

  1. 设置了路由,URL被识别到某个表单页面。
  2. 页面加载,控制器设置变量,指令被触发。
  3. 触发一个特殊格式指令,该指令使用AJAX执行特殊格式提交。
  4. 执行完AJAX之后(Angular不会处理AJAX),便会触发回调,并且伪指令调用$scope.onAfterSubmit设置位置的函数。

问题在于设置位置后什么也没发生。我也尝试过将位置参数设置/为……不。我也尝试过不提交表格。什么都没有。

我已经测试过,看看代码是否达到了onAfterSubmit功能(确实如此)。

我唯一的想法是(由于从指令调用了它)函数的作用域以某种方式改变了,但是onAfterSubmit如果作用域改变了,它又怎么能调用呢?

这是我的代码

var Ctrl = function($scope, $location, $http) {
  $http.get('/resources/' + $params.id + '/edit.json').success(function(data) {
    $scope.resource = data;
  });

  $scope.onAfterSubmit = function() {
    $location.path('/').replace();
  };
}
Ctrl.$inject = ['$scope','$location','$http'];

有人可以帮我吗?



请记住,它是在那一年之前创建的。
matsko 2014年

正确,又多了一年,另一个人得到了更准确正确的公认答案。
Jim G.

1
@吉姆 这不是重复的,这个问题是4年前,您链接的是2年前。
卡斯特罗·罗伊

Answers:


298

几天前我也遇到过类似的问题。在我的情况下,问题是我使用第三方库(准确地说是jQuery)更改了内容,在这种情况下,即使调用函数和设置变量有效,Angular也不总是知道有更改,因此从不进行摘要。

$ apply()用于从角度框架外部以角度执行表达式。(例如,来自浏览器DOM事件,setTimeout,XHR或第三方库)。

$scope.$apply()更改位置并致电replace()Angular 后,请立即尝试使用,以告知发生了变化。


1
奇迹般有效。我已经在您的帖子中添加了我使用的代码以使其正常工作:)非常感谢!!!
matsko

4
为了更好地了解$ apply如何与angular一起使用以及如何解决它的问题,这是该yearofmoo.com/2012/10/…
matsko 2012年

2
@Skeater您可以简单地注入根范围并对其进行如下操作:factory('xyz',['$ rootScope',function($ rootScope){...}])
F Lekschas

4
可以用$ timeout包装您的回调,并且将正确应用范围
JasonS 2013年

7
就像JasonS所说的那样,使用$ timeout(function(){//在此处应用更改}); 这有两个优点:1)您不需要访问$ scope。2)您不必担心$ apply alredy运行。由于第二个原因,使用$ timeout通常是首选方法。
ArneHugo 2014年

56

而不是$location.path(...)改变或刷新页面,我使用的服务$window。在Angular中,此服务用作window对象的接口,并且该window对象包含location使您能够处理与位置或URL内容相关的操作的属性。

例如,window.location您可以分配一个新页面,如下所示:

$window.location.assign('/');

或刷新它,如下所示:

$window.location.reload();

它为我工作。它与您的预期有所不同,但可以实现给定的目标。


3
我也是,URL包含参数时,$ location.path()不会重定向
Sudhakar

2
这是正确的答案。看到这里
Irving

28

我遇到了同样的问题,但是我对$ location的调用已经在摘要中了。调用$ apply()只会产生一个$ digest已经在处理中的错误。

这个技巧奏效了(并确保注入$location到您的控制器中):

$timeout(function(){ 
   $location...
},1);

虽然不知道为什么这是必要的...


5
不,这是一个坏主意。只要检查阶段是否在摘要中即可,然后可以跳过申请。Angular将赶上它并自行更改URL:coderwall.com/p/ngisma
matsko 2014年

3
超时对我来说似乎是一个肮脏的hack。如果您的href包含“#”,则$ location.path()无法正常工作。只需将标签上的href =“#”完全删除或将其设置为href =“”,就无需使用$ timeout
Shankar ARUL-jupyterdata.com 2014年6

7
$$ phase是一个私有变量,您不应尝试访问它,因为它可能会在新的angularjs版本中更改。
布莱斯

7
使用$ timeout可能是一个hack,但是使用$$ phase是一个更大的hack。通常,请勿查看或触摸任何以$$为前缀的内容。
nilskp 2014年

3
经过大约10个小时的随机中断后,此解决方案对我有用!
沙克尔2015年

6

我必须$location.path()像这样嵌入我的声明,因为我的摘要仍在运行:

       function routeMe(data) {                
            var waitForRender = function () {
                if ($http.pendingRequests.length > 0) {
                    $timeout(waitForRender);
                } else {
                    $location.path(data);
                }
            };
            $timeout(waitForRender);
        }

1
谢谢你的功能,非常有用!
Bill Effin Murray

对我来说,问题是我们使用的是angular-block-ui,它阻止了地址栏位置的更新。我们用bool装饰了$ http请求,我们的requestFilter拾取了bool,这样block-ui不会在该特定调用上触发,然后一切都很好。
matao

2

就我而言,问题是模板配置中缺少可选参数指标('?')。

例如:

.when('/abc/:id?', {
    templateUrl: 'views/abc.html',
    controller: 'abcControl'
})


$location.path('/abc');

没有查询字符,路由显然不会改变,从而抑制了路由参数。


不是模板配置,而是路由配置。
Piotr Dobrogost

1

如果您使用的是Angular-ui / ui-router,请使用:$state.go('yourstate')而不是$location。它对我有用。


0

这对我来说很麻烦(在CoffeeScript中)

 $location.path '/url/path'
 $scope.$apply() if (!$scope.$$phase)

0

在我看来,这里的许多答案似乎有些怪异(例如$ apply()或$ timeout),因为弄乱$ apply()可能会导致不必要的错误。

通常,当$ location不起作用时,这意味着某些事情没有以角度的方式实现。

在这个特定问题中,问题似乎出在非角度AJAX部分。我有一个类似的问题,使用$ location的重定向应在诺言解决后进行。我想在这个例子中说明问题。

旧代码:

taskService.createTask(data).then(function(code){
            $location.path("task/" + code);
        }, function(error){});

注意:taskService.createTask返回一个Promise。

$ q-使用promise的角度方式:

let dataPromises = [taskService.createTask(data)];
        $q.all(dataPromises).then(function(response) {
                let code = response[0];
                $location.path("task/" + code);
            }, 
            function(error){});

使用$ q来解决诺言可以解决重定向问题。

有关$ q服务的更多信息:https : //docs.angularjs.org/api/ng/service/ $ q


-8
setTimeout(function() { $location.path("/abc"); },0);

它应该可以解决您的问题。


1
运行non-setTimeout是一个非常糟糕的主意。而且,正如@matsko上面所说,$ timeout不是最好的主意。
gonzofish 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.