AngularJS: Change hash and route without completel

2019-01-16 10:20发布

I have a controller, with a route like this:

#/articles/1234

I want to change the route without completely reloading the controller, so I can keep the position of other stuff in the controller constant (lists that scroll)

I can think of a few ways to do this, but they're all pretty ugly. Is there a best practice for doing something like this? I tried experimenting with reloadOnSearch: false, but it doesn't seem to change anything.

10条回答
再贱就再见
2楼-- · 2019-01-16 10:51

Had the very same challange,

Found a hack in another StackOverflow response that did the trick

Fairly clean solution - all I did was to add these lines to the controller that sets $location.path:

var lastRoute = $route.current;
$scope.$on('$locationChangeSuccess', function(event) {
    $route.current = lastRoute;
});

..and made sure $route in injected into the controller of course.

But still, feels like "DoNotFollowRoutesOnPathChange" is a missing feature in AngularJS.

/Jens

Update: Since listening to this event effectively kills further usage of $routeProvider configs, I had to limit this catch to current path only:

    var lastRoute = $route.current;
    if ($route.current.$route.templateUrl.indexOf('mycurrentpath') > 0) {
        $route.current = lastRoute;         
    }

Getting ugly...

查看更多
劳资没心,怎么记你
3楼-- · 2019-01-16 10:53

Brief Answer:

You can use the $location.search() method as you mentioned. You should listen to the "$routeUpdate" event on scope instead of other route events. $route API.

Explanation:

  1. First of all (you already know), add reloadOnSearch: false to your $routeProvider:

    $routeProvider.when('/somewhere', {
        controller: 'SomeCtrl',
        reloadOnSearch: false
    })
    
  2. Change your anchor tag href or ng-href to href="#/somewhere?param=value" this will trigger $routeChangeSuccess event if the path part (/somewhere) is not the same as current location. Otherwise it will trigger $routeUpdate event.

  3. Listen event on scope:

    $scope.$on("$routeUpdate", function(event, route) {
        // some code here
    });
    
  4. If you want to change search params in code, you can use $location.search() method. $location.search API.

查看更多
唯我独甜
4楼-- · 2019-01-16 10:53

This simple solution (surprisingly) works for me:

$state.params.id = id;  //updating the $state.params somehow prevents reloading the state
$location.path('/articles/' + id);

It doesn't prevent the state reloading on Back and forward button though. Note: I'm using angularjs 1.2.7 and ui-router 0.0.1 (I know it's old).

查看更多
爷的心禁止访问
5楼-- · 2019-01-16 10:56

You can do this without the $locationChange~ and HistoryState hacks using routes resolve promise option.

Assuming you had an article route where that number is what changed you could do this;

$routeProvider.when(
    '/article/:number',
    {
        templateUrl : 'partial.html',
        controller : 'ArticleCtrl',
        resolve : {
            load : ['$q', '$routeParams', function($q, $routeParams) {
                var defer = $q.defer();

                //number was specified in the previous route parameters, means we were already on the article page
                if ($routeParams.number)
                    //so dont reload the view
                    defer.reject('');
                //otherwise, the number argument was missing, we came to this location from another route, load the view
                else
                    defer.resolve();

                return defer.promise;
            }]
        }
    }
);
查看更多
登录 后发表回答