禁止在查询参数更改时重新加载基于ui-router的视图

时间:2014-01-29 08:07:44

标签: angularjs anchor angular-ui-router

更新了问题

标题中的问题仍然存在 - 是否可以捕获?parameters并取消视图重新加载。

原始问题: 我需要为我的应用程序添加锚点支持(锚点到主题)。

这是我有多远:

angular.module('app.topics', [
    'ui.state',
    'ui.router',
    'restangular'
    'app.topics.controllers'
])
.config(function config($stateProvider) {
    $stateProvider.state('viewtopic', {
        url: '/topics/:slug?section',
        onEnter: function($stateParams) {
            // Works, as state has been reloaded.
            console.log('$stateParams', $stateParams);
        },
        resolve: {
            topic: function ($stateParams, Topic) {
                // Wrapper around Restangular. Returns promise.
                return new Topic().get($stateParams.slug);
            }
        },
        views: {
            'main': {
                controller: 'TopicCtrl',
                templateUrl: 'topics/templates/details.tpl.html'
            },
            'sidebar': {
                controller: 'SidebarCtrl',
                templateUrl: 'topics/templates/sidebar.tpl.html'
            }
        }
    });
});

angular.module('app.topics.controllers', [])
    .controller('TopicCtrl', function ($scope, topic, $rootScope, $location,
                                         $anchorScroll, $stateParams) {
        $scope.topic = topic;
        $scope.slug = $stateParams.slug;
        $scope.section = $stateParams.section;
        // ..

        $scope.$watch('$stateParams.section', function (newValue, newValue) {
            // Does not work.
            console.log('stateParams.section changed', newValue, newValue);
        });
    });

我的根本问题是,当我点击#/topics/slug-name?section=section-1的链接时,状态会被完全重新加载,而状态又会重新请求主题的数据。如何只是“刷新”查询参数(并在控制器中捕获该事件)但不重新加载状态(以保持数据加载)?

修改

对于我的问题,我没有注意到一个相当简单的解决方案 - 每个AngularJS documentation在“Hashbang和HTML5模式”上 - 最后一个哈希可以通过$location.hash()访问,滚动可以由$anchorScroll()启动

所以我目前的解决方案是:

在控制器中:

$scope.$watch('$location.hash', function () {
    _.defer($anchorScroll);
});

需要延迟,因为内容可能尚未解析且没有内容。

在模板中,我只需将目标设置为#/topics/slug-name#section-name

3 个答案:

答案 0 :(得分:20)

我的两分钱

首先检查有关将reloadOnSearch设置为false的@doodeec答案:

{
    route:'/',
    resolve: {
        templateUrl:'template.html',
        reloadOnSearch: false
    }
},

然后在控制器上你要抓住这个:

/* Setup to detect when there is a change in the search */
$scope.$on('$routeUpdate', function(next, current) {
   // Do something when routeupdate is called. 
});

我想要更改搜索:

$location.search({'slide_id': slide_id})

还要小心一点:

如果您的路线参数没有更改(或更改为相同的值),因为重新加载已禁用,那么您可能需要强制更改位置:

$scope.$emit('$locationChangeSuccess');

来自评论:

如果没有ngRoute,则不会有$ routeUpdate事件。在这种情况下,您需要收听$scope.$on('$locationChangeSuccess', ...)而不是

答案 1 :(得分:13)

您是否在路由定义中尝试了reloadOnSearch参数?

{
    route:'/',
    resolve: {
        templateUrl:'template.html',
        reloadOnSearch: false
    }
},

答案 2 :(得分:4)

这可以通过使用嵌套状态来实现。代码看起来像这样

 $stateProvider.state('viewtopic', {abstract:true,
url:/topics,
resolve: {
            topic: function ($stateParams, Topic) {
                // Wrapper around Restangular. Returns promise.
                return new Topic().get($stateParams.slug);
            }
        },
views: {
templateUrl:<template>
}
});

$stateProvider.state('viewtopic.impl', {abstract:true,
        url: '/:slug?section',
        onEnter: function($stateParams) {
            // Works, as state has been reloaded.
            console.log('$stateParams', $stateParams);
        },

        views: {
            'main': {
                controller: 'TopicCtrl',
                templateUrl: 'topics/templates/details.tpl.html'
            },
            'sidebar': {
                controller: 'SidebarCtrl',
                templateUrl: 'topics/templates/sidebar.tpl.html'
            }
        }

更多阅读 - &gt; https://github.com/angular-ui/ui-router/wiki/Nested-States-%26-Nested-Views