197 votes

Pouvez-vous changer un chemin sans recharger le contrôleur dans AngularJS?

Il a été demandé avant, et à partir des réponses qu'il n'a pas l'air bon. J'aimerais demander, avec cet exemple de code en considération...

Mon app charges de l'élément en cours dans le service qu'il fournit. Il y a plusieurs contrôleurs de manipuler l'élément de données sans le point d'être rechargé.

Mon contrôleurs de recharger l'élément s'il n'est pas encore fixé, sinon, il utilisera actuellement chargées de l'élément de service, entre les contrôleurs.

Problème: je voudrais utiliser des chemins différents pour chaque contrôleur sans recharger Item.html.

1) Est-ce possible?

2) Si cela n'est pas possible, est-il une meilleure approche à avoir un chemin d'accès par le contrôleur de vs ce que je suis venu jusqu'ici?

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

La résolution.

Statut: à l'Aide de la requête de recherche tel que recommandé dans l'acceptation réponse m'a permis de fournir des url différentes sans avoir à recharger le contrôleur 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');
      }
    });
  }
});

Le contenu à l'intérieur de mes partiels sont enveloppées avec des ng-controller=...

121voto

Anders Ekdahl Points 5678

Si vous ne devez pas utiliser d'URL comme #/item/{{item.id}}/foo et #/item/{{item.id}}/bar mais #/item/{{item.id}}/?foo et #/item/{{item.id}}/?bar place, vous pouvez définir votre itinéraire pour /item/{{item.id}}/ pour que reloadOnSearch soit défini sur false ( docs.angularjs.org/api/ngRoute.$routeProvider ). Cela indique à AngularJS de ne pas recharger la vue si la partie de recherche de l'URL change.

94voto

Vigrond Points 4222

Si vous devez changer le chemin, ajoutez-le après votre fichier .config dans votre fichier d'application. Ensuite, vous pouvez faire $location.path('/sampleurl', false); pour empêcher le rechargement

    app.run(['$route', '$rootScope', '$location', function ($route, $rootScope, $location) {
        var original = $location.path;
        $location.path = function (path, reload) {
            if (reload === false) {
                var lastRoute = $route.current;
                var un = $rootScope.$on('$locationChangeSuccess', function () {
                    $route.current = lastRoute;
                    un();
                });
            }
            return original.apply($location, [path]);
        };
    }])
 

Le crédit va à http://joelsaupe.com/programming/angularjs-change-path-without-reloading/ pour la solution la plus élégante que j'ai trouvée.

10voto

Lukus Points 592

Bien que ce post est vieux, et il a eu une réponse acceptée, à l'aide de reloadOnSeach=false ne résout pas le problème pour ceux d'entre nous qui ont besoin de changer de chemin d'accès réel et pas seulement les paramètres. Voici une solution simple à prendre en compte:

Utilisation ng-inclure au lieu de ng-view et affecter votre contrôleur dans le modèle.

<!-- In your index.html - instead of using ng-view -->
<div ng-include="templateUrl"></div>

<!-- In your template specified by app.config -->
<div ng-controller="MyController">{{variableInMyController}}</div>

//in config
$routeProvider
  .when('/my/page/route/:id', { 
    templateUrl: 'myPage.html', 
  })

//in top level controller with $route injected
$scope.templateUrl = ''

$scope.$on('$routeChangeSuccess',function(){
  $scope.templateUrl = $route.current.templateUrl;
})

//in controller that doesn't reload
$scope.$on('$routeChangeSuccess',function(){
  //update your scope based on new $routeParams
})

Le seul côté, c'est que vous ne pouvez pas utiliser de résoudre attribut, mais c'est assez facile de se déplacer. Aussi, vous avez à gérer l'état du contrôleur, à l'instar de la logique basée sur $routeParams que les modifications d'itinéraire dans le contrôleur comme l'url correspondant à des changements.

Voici un exemple: http://plnkr.co/edit/WtAOm59CFcjafMmxBVOP?p=preview

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X