2012-09-14 32 views
38

我的单页应用程序加载主页,我想显示一系列想法。每个想法都显示在动画Flash容器中,动画显示为在想法之间循环。

想法是使用加载的$ HTTP:

$scope.flash = new FlashInterface scope:$scope,location:$location 

$http.get("/competition.json") 
    .success (data) -> 
    $scope.flash._init data 

但是,从历史的导航和UX受益我希望更新的地址栏使用$位置来显示每个想法正确的网址:

​​

我打电话给$在这里适用,因为这个事件来自AngularJS上下文,即Flash。我希望当前的控制器/视图保持不变,并且视图不能重新加载。这非常糟糕,因为重新加载视图会导致整个Flash对象被丢弃,并且preloader循环再次开始。

我试着聆听$ routeChangeStart做的preventDefault:

$scope.$on "$routeChangeStart", (ev,next,current) -> 
    ev.preventDefault() 
$scope.$on "$routeChangeSuccess", (ev,current) -> 
    ev.preventDefault() 

,但无济于事。如果我可以在更改$ location.path的时候找出覆盖视图重新加载的方式,那么整个事情就会是hunky dory。

我仍然非常感觉我的AngularJS的方式,所以我会很高兴有关如何构建应用程序来实现我的目标的任何指针!

+0

我迟到了,但我刚刚遇到类似的问题。是否有理由不能将'ideas'放在'ng-view'指令之外,并给它们自己的控制器,它通过作用域继承与'ng-view'内的控制器交互?我主要是问,因为这是我如何解决自己的问题,并想知道它是否有任何缺点,或者如果我切换到接受的答案。 – jclancy

+1

如果我今天再次解决这个问题,我会非常想用ui-路由器的分层视图功能。我不确定这会解决我在这里遇到的特定URL问题,但需要更多研究一段时间......! – chrisbateskeegan

+0

好的,谢谢你指出我在那个方向,并感谢回应这样一个迟到的评论! – jclancy

回答

92

而不是更新路径,只需更新页面编号的查询参数。

设置你的路线,忽略查询参数的变化:

.... 
$routeProvider.when('/foo', {..., reloadOnSearch: false}) 
.... 

,并在您的应用程序更新$location有:

... 
$location.search('page', pageNumber); 
... 
+10

谢谢你的提示,伊戈尔。之前我发现并贴现了这个问题,因为我更喜欢URL如'/ idea/Acas'而不是'/ foo?idea = Acas'。然而,它确实有工作的美德,并且在实用主义者的世界里工作胜过完美! – chrisbateskeegan

+5

完美的,非常感谢这个提示。 此外,我要注意,如果你要检测的参数改变,你可以做到这一点: $范围在$(“$路由更新”功能(){// 搜索PARAM改变 }) – Unitech

+0

这是答案!所有这些其他的答案,我发现处理$ route和$ state的处理,这是直截了当的,并完成工作! –

30

this blog post

默认情况下,所有地点更改都要经过路由过程, 更新斜视。

但是,有一种简单的方法可以将其短路。有角手表 用于位置更改(无论是通过在地址栏中输入 地址栏,单击链接或通过 $location.path()设置位置来完成)。当它感知到这种变化时,它会广播一个 事件,$locationChangeSuccess,并开始路由过程。我们所做的是捕获事件并将路线重置为之前的 。

function MyCtrl($route, $scope) { 
    var lastRoute = $route.current; 
    $scope.$on('$locationChangeSuccess', function(event) { 
     $route.current = lastRoute; 
    }); 
} 
+0

感谢您的支持,这听起来就像我一直在寻找的解决方案。我已经阅读了博客文章并发挥了很好的作用。不幸的是,它似乎并不奏效。我试着将代码放在'$ routeChangeStart'中,看看这是否会有所作为,但无济于事。有没有可能是我失踪的巫术? – chrisbateskeegan

+0

另一个想法:尝试设置reloadOnSearch = false,http://docs.angularjs.org/api/ng.$ro​​uteProvider 另请参阅https://github.com/angular/angular.js/pull/1151 –

+2

这是一个可怕的,可怕的黑客...但它的工作。直到Angular提供了一些方法将位置更新事件与重新加载解耦(不幸的是,默认情况下,默认情况下可以防止url更改),这正是我们正在使用的。是的,fwiw,reloadOnSearch = false如果你需要改变的仅限于搜索参数,那么它的效果很好。我们的问题是可收藏标签的散列。 – zapnap

1

你应该通过加载依赖注入$location并使用下列内容:

$scope.apply(function() { 
    $location.path("yourPath"); 
} 

请记住,你应该使用#标签(#),而使用$location.path。这是为了HTML5模式的兼容性。

+1

感谢您的提示。我_think_正确加载$位置'IndexController =($ scope,$ http,$ location,$ route) - >'我已经更新了应用代码,正如你所建议的那样。我并不确定这种差异究竟有多大,你能否详细说明一下? – chrisbateskeegan

3

我的解决办法是使用$ routeChangeStart因为这样可以给你的“下“和”最后“路线,您可以比较它们而不需要像$ locationChangeSuccess这样的额外变量。

的好处是能够当您使用“/属性/值” URL风格,当然使用$location.url$location.path改变访问“PARAMS”属性上都“下一个”和“最后一个”路线像next.params.yourproperty URL取代了$location.search(),取决于“?property = value”的URL风格。

在我来说,我用它不仅如此,但同时也防止对改变路由控制器并没有改变:

$scope.$on('$routeChangeStart',function(e,next,last){ 
    if(next.$$route.controller === last.$$route.controller){ 
    e.preventDefault(); 
    $route.current = last.$$route; 
    //do whatever you want in here! 
    } 
}); 

我个人觉得像AngularJS应该提供一种方法来控制它,正确的现在他们假设每当你改变浏览器的位置时,你都想改变路线。

+1

在AngularJS 1.2.6的控制器中尝试使用它时,这不起作用。我认为它是相关的$ routeChangeStart是不可预防的广播:http://stackoverflow.com/a/14895801/959140 –

0

的$ locationChangeSuccess事件是有点蛮力的办法,但我发现,检查路径使我们避免了页面重新加载时布线路径模板不变,但重新加载页面切换到不同的路由时,模板:

var lastRoute = $route.current; 
$scope.$on('$locationChangeSuccess', function (event) { 
    if (lastRoute.$$route.originalPath === $route.current.$$route.originalPath) { 
     $route.current = lastRoute; 
    } 
}); 

将该代码添加到特定的控制器使重新加载更加智能化。

编辑:虽然这使它更容易一些,但我最终不喜欢我写的代码的复杂性,以保持友好的URL。最后,我只是切换到一个搜索参数和角度处理它好得多。

0

我需要这样做,但在尝试让$locationChange~事件启动后,我发现可以使用resolveroute上做到这一点。

$routeProvider.when(
    '/page', 
    { 
     templateUrl : 'partial.html', 
     controller : 'PageCtrl', 
     resolve : { 
      load : ['$q', function($q) { 
       var defer = $q.defer(); 

       if (/*you only changed the idea thingo*/) 
        //dont reload the view 
        defer.reject(''); 
       //otherwise, load the view 
       else 
        defer.resolve(); 

       return defer.promise; 
      }] 
     } 
    } 
);