Pytanie zostało zadane wcześniej, a na podstawie odpowiedzi nie wygląda dobrze. Chciałbym zapytać o ten przykładowy kod ...
Moja aplikacja ładuje bieżący element do usługi, która go udostępnia. Istnieje kilka kontrolerów, które manipulują danymi elementu bez ponownego ładowania elementu.
Moi kontrolerzy ponownie załadują element, jeśli nie został jeszcze ustawiony, w przeciwnym razie użyją aktualnie załadowanego elementu z usługi między kontrolerami.
Problem : Chciałbym użyć różnych ścieżek dla każdego kontrolera bez ponownego ładowania pliku Item.html.
1) Czy to możliwe?
2) Jeśli nie jest to możliwe, czy istnieje lepsze podejście do posiadania ścieżki na kontroler niż to, co tutaj wymyśliłem?
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);
}
Rozkład.
Status : użycie zapytania wyszukiwania zgodnie z zaleceniami w zaakceptowanej odpowiedzi pozwoliło mi podać różne adresy URL bez ponownego ładowania głównego kontrolera.
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');
}
});
}
});
Treść w moich stronicach jest zapakowana ng-controller=...
Odpowiedzi:
Jeśli nie trzeba używać adresów jak
#/item/{{item.id}}/foo
i#/item/{{item.id}}/bar
ale#/item/{{item.id}}/?foo
i#/item/{{item.id}}/?bar
zamiast tego można skonfigurować trasy dla/item/{{item.id}}/
miećreloadOnSearch
zestaw dofalse
( https://docs.angularjs.org/api/ngRoute/provider/$routeProvider ). To mówi AngularJS, aby nie przeładowywał widoku, jeśli zmieni się część wyszukiwania adresu URL.źródło
ng-controller="view.controller"
dong-include
dyrektywy.<div ng-controller="itemFooCtrl">... your template content...</div>
. EDYCJA: Miło cię widzieć z rozwiązaniem, byłoby wspaniale, gdybyś zaktualizował swoje pytanie o to, jak rozwiązałeś, być może za pomocą jsFiddle.Jeśli chcesz zmienić ścieżkę, dodaj ją po pliku .config w pliku aplikacji. Następnie możesz zrobić,
$location.path('/sampleurl', false);
aby zapobiec przeładowaniuKredyt trafia do https://www.consolelog.io/angularjs-change-path-without-reloading za najbardziej eleganckie rozwiązanie, jakie znalazłem.
źródło
$timeout(un, 200);
instrukcję return przed zwrotem, ponieważ czasem$locationChangeSuccess
wcale się nie uruchamiałapply
(a trasa nie została zmieniona, gdy była naprawdę potrzebna). Moje rozwiązanie rozwiązuje problem po wywołaniu ścieżki (..., false)dlaczego po prostu nie ustawić kontrolera ng o jeden poziom wyżej,
I nie ustawiaj kontrolera na trasie,
mi to pasuje.
źródło
Dla tych, którzy potrzebują zmiany path () bez ponownego ładowania sterowników - oto wtyczka: https://github.com/anglibs/angular-location-update
Stosowanie:
Na podstawie https://stackoverflow.com/a/24102139/1751321
PS To rozwiązanie https://stackoverflow.com/a/24102139/1751321 zawiera błąd po wywołaniu ścieżki (, false) - spowoduje przerwanie nawigacji przeglądarki do tyłu / do przodu, dopóki ścieżka ((prawda) nie zadzwoni
źródło
Chociaż ten post jest stary i ma zaakceptowaną odpowiedź, użycie reloadOnSeach = false nie rozwiązuje problemu dla tych z nas, którzy muszą zmienić rzeczywistą ścieżkę, a nie tylko parametry. Oto proste rozwiązanie do rozważenia:
Użyj ng-include zamiast ng-view i przypisz kontroler do szablonu.
Jedynym minusem jest to, że nie można użyć atrybutu resolver, ale dość łatwo można go obejść. Musisz także zarządzać stanem kontrolera, na przykład logiką opartą na $ routeParams, gdy trasa zmienia się w kontrolerze, gdy zmienia się odpowiedni adres URL.
Oto przykład: http://plnkr.co/edit/WtAOm59CFcjafMmxBVOP?p=preview
źródło
Korzystam z tego rozwiązania
Takie podejście zachowuje funkcję przycisku Wstecz i zawsze masz bieżące routeParams w szablonie, w przeciwieństwie do niektórych innych podejść, które widziałem.
źródło
Odpowiedzi powyżej, w tym GitHub, miały pewne problemy z moim scenariuszem, a także przycisk Wstecz lub bezpośrednia zmiana adresu URL z przeglądarki ładowała kontroler, co mi się nie podobało. W końcu zastosowałem następujące podejście:
1. Zdefiniuj właściwość w definicjach tras, zwaną „noReload” dla tych tras, w których nie chcesz, aby kontroler ładował się ponownie po zmianie trasy.
2. W funkcji uruchamiania modułu umieść logikę, która sprawdza te trasy. Zapobiegnie to przeładowaniu tylko wtedy, gdy
noReload
jest,true
a poprzedni kontroler trasy jest taki sam.3. Na koniec, w kontrolerze, nasłuchuj zdarzenia $ routeUpdate, abyś mógł zrobić wszystko, co musisz zrobić, gdy zmienią się parametry trasy.
Pamiętaj, że przy takim podejściu nie zmieniasz rzeczy w kontrolerze, a następnie odpowiednio aktualizujesz ścieżkę. Jest na odwrót. Najpierw zmieniasz ścieżkę, a następnie nasłuchujesz zdarzenia $ routeUpdate, aby zmienić rzeczy w kontrolerze po zmianie parametrów trasy.
Dzięki temu wszystko jest proste i spójne, ponieważ możesz używać tej samej logiki zarówno po prostu zmieniając ścieżkę (ale bez drogich żądań $ http, jeśli chcesz), jak i po całkowitym przeładowaniu przeglądarki.
źródło
Istnieje prosty sposób zmiany ścieżki bez ponownego ładowania
Użyj tego kodu, aby zmienić adres URL, strona nie zostanie przekierowana
Drugi parametr „false” jest bardzo ważny.
źródło
Oto moje pełniejsze rozwiązanie, które rozwiązuje kilka rzeczy, których @Vigrond i @rahilwazir przegapili:
$routeUpdate
.$locationChangeSuccess
nigdy się nie uruchamia, co powoduje następne uniemożliwia aktualizację trasy.Jeśli w tym samym cyklu podsumowania pojawiło się kolejne żądanie aktualizacji, tym razem chcąc przeładować, program obsługi zdarzeń anuluje to przeładowanie.
źródło
path
na końcu powinna byćparam
, również to nie działa z hashami, a adres URL w moim pasku adresu nie aktualizuje sięDodaj następujący znacznik głowy
Zapobiegnie to przeładowaniu.
źródło
Od wersji 1.2 możesz użyć $ location.replace () :
źródło