Paging AngularJS com $ location.path mas sem recarregar ngView

Meu aplicativo de página única carrega uma home page e desejo exibir uma série de ideias. Cada uma das ideias é exibida em um contêiner flash animado, com animações exibidas para alternar entre as ideias.

As ideias são carregadas usando $ http:

$scope.flash = new FlashInterface scope:$scope,location:$location $http.get("/competition.json") .success (data) -> $scope.flash._init data 

No entanto, para me beneficiar da navegação do histórico e do UX, desejo atualizar a barra de endereço para exibir o URL correto para cada ideia usando $ location:

 $location.path "/i/#{idea.code}" $scope.$apply() 

Eu estou chamando $ apply aqui porque este evento vem de fora do contexto AngularJS, ou seja, Flash. Eu gostaria que o controlador / view atual permanecesse e que a visualização não fosse recarregada. Isso é muito ruim porque recarregar os resultados da visualização em todo o object flash sendo jogado fora e o ciclo do pré-carregador começa novamente.

Eu tentei escutar $ routeChangeStart para fazer um preventDefault:

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

mas sem sucesso. A coisa toda seria ótima se eu conseguisse descobrir uma maneira de replace o recarregamento da visão quando eu alterasse o $ location.path.

Eu ainda estou me sentindo muito ao redor do AngularJS, então eu ficaria feliz com qualquer indicação de como estruturar o aplicativo para alcançar meu objective!

Em vez de atualizar o caminho, basta atualizar o parâmetro de consulta com um número de página.

defina sua rota para ignorar alterações de parâmetros de consulta:

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

e na sua atualização do aplicativo $location com:

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

Desta postagem do blog :

Por padrão, todas as alterações de localização passam pelo processo de roteamento, que atualiza a visualização angular.

Há uma maneira simples de contornar isso, no entanto. Relógios angulares para uma mudança de local (seja ele feito digitando na barra de localização, clicando em um link ou definindo o local através de $location.path() ). Quando detecta essa alteração, ele transmite um evento, $locationChangeSuccess e inicia o processo de roteamento. O que fazemos é capturar o evento e redefinir a rota para o que era anteriormente.

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

Minha solução foi usar o $ routeChangeStart, porque isso dá a você as rotas “next” e “last”, você pode compará-las sem a necessidade de uma variável extra, como em $ locationChangeSuccess.

O benefício é poder acessar a propriedade “params” nas rotas “next” e “last” como next.params.yourproperty quando você estiver usando o estilo de URL “/ property / value” e, é claro, usar $location.url ou $location.path para alterar o URL em vez de $location.search() que depende do estilo de URL “? property = value”.

No meu caso eu usei não só para isso, mas também para evitar que a rota mude é o controlador não mudou:

 $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! } }); 

Pessoalmente, sinto que o AngularJS deve fornecer uma maneira de controlá-lo. Agora, eles assumem que, sempre que você alterar a localização do navegador, você deseja alterar a rota.

Você deve estar carregando $location via Dependency Injection e usando o seguinte:

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

Tenha em mente que você não deve usar hashtags (#) ao usar $location.path . Isto é para compatibilidade com o modo HTML5.

O evento $ locationChangeSuccess é uma abordagem de força bruta, mas descobri que a verificação do caminho nos permite evitar recarregamentos de página quando o modelo de caminho de rota não é alterado, mas recarrega a página ao alternar para um modelo de rota diferente:

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

Adicionar esse código a um determinado controlador torna o recarregamento mais inteligente.

Edit: Enquanto isso torna um pouco mais fácil, eu finalmente não gostei da complexidade do código que eu estava escrevendo para manter URLs de aparência amigável. No final, eu apenas mudei para um parâmetro de pesquisa e angular manipula muito melhor.

Eu precisava fazer isso, mas depois de reclamar tentando obter os events $locationChange~ para fazê-lo funcionar, aprendi que você pode fazer isso na route usando resolve .

 $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; }] } } );