-
Notifications
You must be signed in to change notification settings - Fork 27.4k
Option on $location to allow hash/path change w/o reloading the route #1699
Comments
+1, having the same issue. |
@cgross Since the $location service uses JQuery-style method chaining, and all commands are deferred until $digest anyway, I suggest adding a new chaining method, e.g. reload(boolean):
P.S. Is this the Chris Gross that started the Eclipse Nebula project? |
Yup :) |
+1 👍 |
+1 Right now, we're using a dirty hack to get around this problem.
|
+1 |
4 similar comments
+1 |
+1 |
+1 |
+1 |
Here is my attempt at fixing this by supporting |
This adds a new method `notify` to `$location` that allows updating the location without triggering `$locationChangeStart`/`$locationChangeSuccess` events. The method is chainable and must be called with a boolean parameter. Any falsy value will disable the notification procedure and will block any route update that may apply. The skip flag will be reset after any digest cycle, so it must be set again on any subsequent change if needed. Example: `$location.path('/client/2').replace().notify(false);` Closes angular#1699
I've been working into @qualidafial approach for a few days and now the PR is ready. I've created a new This doesn't touch the routing system, so you don't have to change your route definitions. It will still work even if you use Example: I've also worked some tests and documentation bits. |
+1 |
another +1 |
+1 |
+1 |
Unfortunately PR #2398 has been rejected by the Angular team as skipping notifications could lead to inconsistencies between the actual URL and the current route. There is a long explanation at the end of the discussion. I don't need this feature in any of my projects, but I'll keep it in my repository so it can be merged if you wish. Just let me know if it gets out of sync with the master branch so I can rebase the changes. Thanks! |
+1 |
+1, need this :( |
+1 |
Edit: better approach here: #1699 (comment) I've created a reusable factory to bypass this (based on the idea from @shahmirn): /**
* HACK Do not reload the current template if it is not needed.
*
* See AngularJS: Change hash and route without completely reloading controller http://stackoverflow.com/questions/12115259/angularjs-change-hash-and-route-without-completely-reloading-controller
*/
app.factory('DoNotReloadCurrentTemplate', ['$route', function($route) {
return function(scope) {
var lastRoute = $route.current;
scope.$on('$locationChangeSuccess', function() {
if (lastRoute.$$route.templateUrl === $route.current.$$route.templateUrl) {
console.log('DoNotReloadCurrentTemplate not reloading template: ' + $route.current.$$route.templateUrl);
$route.current = lastRoute;
}
});
};
}]); How to use: app.controller('MyCtrl',
['$scope', 'DoNotReloadCurrentTemplate',
function($scope, DoNotReloadCurrentTemplate) {
DoNotReloadCurrentTemplate($scope);
}]); |
If you set "reloadOnSearch" to false on the route then it seems to fix the hash changes reloading the whole page. |
+1 This would be great for mobile apps, where the ng-view create/destroy lifecycle is not appropriate (kills performance and usability). |
@tkrotoff Thanks for the example. Since your workaround is cancelling event notifications I've added a broadcast on the rootscope so other controllers can still be notified of the route change: /**
* HACK Do not reload the current template if it is not needed.
*
* See AngularJS: Change hash and route without completely reloading controller http://stackoverflow.com/questions/12115259/angularjs-change-hash-and-route-without-completely-reloading-controller
*/
app.factory('DoNotReloadCurrentTemplate', ['$route', '$rootScope', function($route, $rootScope) {
return function(scope) {
var lastRoute = $route.current;
scope.$on('$locationChangeSuccess', function() {
if (lastRoute.$$route.templateUrl === $route.current.$$route.templateUrl) {
console.log('DoNotReloadCurrentTemplate not reloading template: ' + $route.current.$$route.templateUrl);
$rootScope.$broadcast('locationChangedWithoutReload', $route.current);
$route.current = lastRoute;
}
});
};
}]); Then: app.controller('MyCtrl',
['$scope', 'DoNotReloadCurrentTemplate',
function($scope, DoNotReloadCurrentTemplate) {
DoNotReloadCurrentTemplate($scope);
$rootScope.$on('locationChangedWithoutReload', function(event, route) {
// set location specific breadcrumbs
$scope.breadcrumbs = assembleBreadCrumbs();
// do something for specific route
if (route.$$route.action == 'item') {
$scope.item = $scope.items[params.itemId];
$rootScope.title = $scope.item.name;
}
});
}]); |
I have the same issue as the topic author has and created modified version of solution described above.
Usage:
Using permanent event listener that tests templateUrl to decide whether to allow route reload, could break routing to other views that uses same templateUrl. For example, I routed to /thing/new and the view shows link to last added thing /thing/5, I'll be unable to navigate to thing 5 and to any other thing (even changing url in browser explicitly). Another problem with templateUrl testing is that templates could be specified by using template property (as string or function). This hack allows to skip exactly one route reload and doesn't break routing. |
+1 |
I confirm that ngSilent is doing perfectly the job. Even so an official solution would be highly appreciated. |
The solution is essentially to add an extra parameter to $location.path().
And then just use like this
|
I should just be able to do $location.replace() just like the window.location.replace function. This is just silly because every Create in a CRUD operation will always have this issue. |
(y) +1 |
+1 |
I advise you use "search param" like this: |
Demo http://codepen.io/dolymood/details/jrEQBx/ |
+1 |
2 similar comments
+1 |
+1 |
Enables users to specify that a particular route should not be reloaded after a URL change (including a change in `$location.path()`), if the new URL maps to the same route. The default behavior is still to always load the matched route when any part of the URL changes. Related to angular#1699, angular#5860, angular#14999 (potentially closing the first two).
+1 |
2 similar comments
+1 |
+1 |
+! |
Enough of the +1s already :-) |
Closed by #15002. |
We have a paradigm in our app that user's create new things on the same page that they view things. So our route is like /thing/:id. When creating a new thing they go to /thing/new. Once the thing has been successfully saved we want to change the route to /thing/1234 (or whatever its new id is). Now the partial doesnt need to be reloaded because the data is all the same. We just want the path to be updated so a user can now bookmark the correct link, etc.
Having an option on $location (not on the route definition) to enable/disable route loading would work but I'm sure there are other ways to implement the feature.
The text was updated successfully, but these errors were encountered: