2012-09-14 27 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; 
      }] 
     } 
    } 
);