Já foi perguntado antes e, pelas respostas, não parece bom. Gostaria de perguntar com este código de exemplo em consideração ...
Meu aplicativo carrega o item atual no serviço que o fornece. Existem vários controladores que manipulam os dados do item sem que o item seja recarregado.
Meus controladores recarregarão o item se ainda não estiver definido, caso contrário, ele usará o item atualmente carregado do serviço entre controladores.
Problema : eu gostaria de usar caminhos diferentes para cada controlador sem recarregar o Item.html.
1) Isso é possível?
2) Se isso não for possível, existe uma abordagem melhor para ter um caminho por controlador versus o que eu vim aqui?
app.js
var app = angular.module('myModule', []).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/items', {templateUrl: 'partials/items.html', controller: ItemsCtrl}).
when('/items/:itemId/foo', {templateUrl: 'partials/item.html', controller: ItemFooCtrl}).
when('/items/:itemId/bar', {templateUrl: 'partials/item.html', controller: ItemBarCtrl}).
otherwise({redirectTo: '/items'});
}]);
Item.html
<!-- Menu -->
<a id="fooTab" my-active-directive="view.name" href="#/item/{{item.id}}/foo">Foo</a>
<a id="barTab" my-active-directive="view.name" href="#/item/{{item.id}}/bar">Bar</a>
<!-- Content -->
<div class="content" ng-include="" src="view.template"></div>
controller.js
// Helper function to load $scope.item if refresh or directly linked
function itemCtrlInit($scope, $routeParams, MyService) {
$scope.item = MyService.currentItem;
if (!$scope.item) {
MyService.currentItem = MyService.get({itemId: $routeParams.itemId});
$scope.item = MyService.currentItem;
}
}
function itemFooCtrl($scope, $routeParams, MyService) {
$scope.view = {name: 'foo', template: 'partials/itemFoo.html'};
itemCtrlInit($scope, $routeParams, MyService);
}
function itemBarCtrl($scope, $routeParams, MyService) {
$scope.view = {name: 'bar', template: 'partials/itemBar.html'};
itemCtrlInit($scope, $routeParams, MyService);
}
Resolução.
Status : o uso da consulta de pesquisa, conforme recomendado na resposta aceita, permitiu fornecer URLs diferentes sem recarregar o controlador principal.
app.js
var app = angular.module('myModule', []).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/items', {templateUrl: 'partials/items.html', controller: ItemsCtrl}).
when('/item/:itemId/', {templateUrl: 'partials/item.html', controller: ItemCtrl, reloadOnSearch: false}).
otherwise({redirectTo: '/items'});
}]);
Item.html
<!-- Menu -->
<dd id="fooTab" item-tab="view.name" ng-click="view = views.foo;"><a href="#/item/{{item.id}}/?view=foo">Foo</a></dd>
<dd id="barTab" item-tab="view.name" ng-click="view = views.bar;"><a href="#/item/{{item.id}}/?view=foo">Bar</a></dd>
<!-- Content -->
<div class="content" ng-include="" src="view.template"></div>
controller.js
function ItemCtrl($scope, $routeParams, Appts) {
$scope.views = {
foo: {name: 'foo', template: 'partials/itemFoo.html'},
bar: {name: 'bar', template: 'partials/itemBar.html'},
}
$scope.view = $scope.views[$routeParams.view];
}
directives.js
app.directive('itemTab', function(){
return function(scope, elem, attrs) {
scope.$watch(attrs.itemTab, function(val) {
if (val+'Tab' == attrs.id) {
elem.addClass('active');
} else {
elem.removeClass('active');
}
});
}
});
O conteúdo das minhas parciais é envolvido com ng-controller=...
Respostas:
Se você não tem que usar URLs como
#/item/{{item.id}}/foo
e#/item/{{item.id}}/bar
, mas#/item/{{item.id}}/?foo
e#/item/{{item.id}}/?bar
em vez disso, você pode definir o seu trajecto para/item/{{item.id}}/
terreloadOnSearch
pronto parafalse
( https://docs.angularjs.org/api/ngRoute/provider/$routeProvider ). Isso informa ao AngularJS para não recarregar a exibição se a parte de pesquisa do URL mudar.fonte
ng-controller="view.controller"
àng-include
diretiva.<div ng-controller="itemFooCtrl">... your template content...</div>
. Edição: É bom ver que você resolveu, seria ótimo se você atualizasse sua pergunta com a forma como resolveu, talvez com um jsFiddle.Se você precisar alterar o caminho, adicione-o após o arquivo .config no arquivo do aplicativo. Então você pode fazer
$location.path('/sampleurl', false);
para impedir o recarregamentoO crédito vai para https://www.consolelog.io/angularjs-change-path-without-reloading para obter a solução mais elegante que encontrei.
fonte
$timeout(un, 200);
antes da declaração de retorno, pois às vezes$locationChangeSuccess
não disparava depoisapply
(e a rota não foi alterada quando realmente necessário). Minha solução apura as coisas após invocação de caminho (..., false)por que não colocar o controlador ng um nível acima,
E não defina o controlador na rota,
funciona para mim.
fonte
Para quem precisa de mudança de path () sem recarregar controladores - Aqui está o plugin: https://github.com/anglibs/angular-location-update
Uso:
Com base em https://stackoverflow.com/a/24102139/1751321
PS Esta solução https://stackoverflow.com/a/24102139/1751321 contém um bug após o caminho (, falso) chamado - ele interromperá a navegação do navegador para trás / para frente até o caminho (, verdadeiro) chamado
fonte
Embora esta postagem seja antiga e tenha uma resposta aceita, o uso de reloadOnSeach = false não resolve o problema para aqueles que precisam mudar o caminho real e não apenas os parâmetros. Aqui está uma solução simples a considerar:
Use ng-include em vez de ng-view e atribua seu controlador no modelo.
A desvantagem é que você não pode usar o atributo resolve, mas isso é muito fácil de contornar. Além disso, você deve gerenciar o estado do controlador, como a lógica baseada em $ routeParams, à medida que a rota muda dentro do controlador à medida que a URL correspondente é alterada.
Aqui está um exemplo: http://plnkr.co/edit/WtAOm59CFcjafMmxBVOP?p=preview
fonte
Eu uso essa solução
Essa abordagem preserva a funcionalidade do botão Voltar e você sempre tem os routeParams atuais no modelo, ao contrário de outras abordagens que já vi.
fonte
As respostas acima, incluindo a do GitHub, tiveram alguns problemas para o meu cenário e também a alteração do botão voltar ou da URL direta do navegador estava recarregando o controlador, o que eu não gostei. Finalmente fui com a seguinte abordagem:
1. Defina uma propriedade nas definições de rota, chamada 'noReload', para aquelas rotas nas quais você não deseja que o controlador recarregue com a mudança de rota.
2. Na função de execução do seu módulo, coloque a lógica que verifica essas rotas. Isso impedirá a recarga apenas se
noReload
houvertrue
e o controlador de rota anterior for o mesmo.3. Finalmente, no controlador, ouça o evento $ routeUpdate para poder fazer o que for necessário quando os parâmetros de rota forem alterados.
Lembre-se de que, com essa abordagem, você não altera as coisas no controlador e atualiza o caminho de acordo. É o contrário. Você primeiro altera o caminho e, em seguida, ouve o evento $ routeUpdate para alterar as coisas no controlador quando os parâmetros de rota são alterados.
Isso mantém as coisas simples e consistentes, pois você pode usar a mesma lógica quando simplesmente muda de caminho (mas sem solicitações caras de $ http, se quiser) e quando recarrega completamente o navegador.
fonte
Existe uma maneira simples de mudar o caminho sem recarregar
Use este código para alterar o URL, a página não será redirecionada
O segundo parâmetro "false" é muito importante.
fonte
Aqui está a minha solução mais completa que resolve algumas coisas que o @Vigrond e o @rahilwazir perderam:
$routeUpdate
.$locationChangeSuccess
nunca é acionada, o que causa a próxima atualização de rota seja impedida.Se no mesmo ciclo de resumo houvesse outra solicitação de atualização, desta vez desejando recarregar, o manipulador de eventos cancelaria essa recarga.
fonte
path
no final deve serparam
, também este não funciona com hashes, ea url na minha barra de endereços não atualizaAdicione a seguinte tag de cabeça interna
Isso impedirá a recarga.
fonte
Desde a versão 1.2, você pode usar $ location.replace () :
fonte