Can you change a path without reloading the controller in AngularJS?

angularjs

Solution

If you don't have to use URLs like `#/item/{{item.id}}/foo` and `#/item/{{item.id}}/bar` but `#/item/{{item.id}}/?foo` and `#/item/{{item.id}}/?bar` instead, you can set up your route for `/item/{{item.id}}/` to have `reloadOnSearch` set to `false` (https://docs.angularjs.org/api/ngRoute/provider/$routeProvider). That tells AngularJS to not reload the view if the search part of the url changes.

Problem

It's been asked before, and from the answers it doesn't look good. I'd like to ask with this sample code in consideration... My app loads the current item in the service that provides it. There are several controllers that manipulate the item data without the item being reloaded. My controllers will reload the item if it's not set yet, otherwise, it will use the currently loaded item from the service, between controllers. Problem: I would like to use different paths for each controller without reloading Item.html. 1) Is that possible? 2) If that is not possible, is there a better approach to having a path per controller vs what I came up with here? 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); } ``` Resolution. Status: Using search query as recommended in the accepted answer allowed me to provide different urls without reloading the main controller. 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'); } }); } }); ``` The content inside my partials are wrapped with `ng-controller=...`

Original source

Related problems