同一模板的多个州和网址

时间:2015-10-29 18:24:23

标签: angularjs angular-ui-router

我正在构建一个Web应用程序,我有一个屏幕,它包含五个部分,每个部分代表一个级别,区域是我的树的更高级别,当我点击该区域的任何卡片时,系统应该返回该区域的技能等。 wireframe

我需要根据用户访问的内容更改网址和状态,例如,如果用户访问某项技能,则网址必须为

example.com/#/curriculum/skill/<skillId>

如果我访问此链接,它应该自动加载此技能及其父级的功能,在这种情况下是区域。

我有一个控制器用于区域,技能,能力,知识和标准,在每个控制器中我都有一个动作来加载树的下一级,看起来像那样

$scope.loadSkills = function (id) {
   Area.loadSkills(...)
   $state.go('curriculo.skill', {id: this.current.id}, {nofity: false, reload: false});
}

这些是我的州

$stateProvider
      .state('curriculum', {
        url: '/curriculum',
        templateUrl: '/templates/curriculo.html',
      })
      .state('curriculum.are', {
        url: '/area/:id',
        template: '',
      })
      .state('curriculum.skill', {
        url: '/skill/:id',
        template: '',
      })
      .state('curriculum.capability', {
        url: '/capability/:id',
      })
      .state('curriculum.knowledge', {
        url: '/knowledge/:id',
      })
      .state('curriculum.criteria', {
        url: '/criteria/:id',
      });

我是Angular的新手,我不知道该怎么做,我应该在这种情况下创建多个嵌套视图,如果是这样,我如何根据网址加载我需要的东西?

1 个答案:

答案 0 :(得分:2)

我建议使用ui-router提供的多个命名视图的功能。您可以阅读更多相关信息here。基本上文档说明如下:

  

您可以为视图命名,以便每个视图可以有多个ui视图   模板。

如果您查看文档中的示例,则表明您的方案与示例之间存在相似之处,因为您希望动态填充其他views(此处为命名视图)。

示例

我尝试在此JSFiddle中重新创建您的方案。

首先,我创建了一个abstract状态,它提供了不同的views类似区域,技能等。这是抽象状态的模板:

<div class="curriculum" ui-view="areas"></div>
<div class="curriculum" ui-view="skills"></div>

接下来,我创建了一个嵌套状态curriculo.main,它声明了您需要的不同视图(区域,技能等)。每个视图都有自己的templatecontroller。请注意,嵌套状态具有resolve,它最初从名为curriculo的服务加载区域。如果您使用结算,请记住,解析关键字必须相对于不是视图的状态(使用多个视图时)。

基本上,服务负责业务逻辑,意味着获取区域,技能等。在JSFiddle中,我已经对HTTP结果进行了硬编码。用HTTP调用替换它并使用promises。由于每个命名视图都有自己的控制器,因此我们需要一种机制来通知更改,例如通知SkillsController已加载技能。因此,我创建了一个简单的事件系统(subcribe-notify):

.factory('notifier', function($rootScope) {
    return {
        subscribe: function(scope, callback, eventName) {
            var handler = $rootScope.$on(eventName, callback);
            scope.$on('$destroy', handler);
        },
        notify: function(eventName, data) {
            $rootScope.$emit(eventName, data);
        }
    };
});

然后SkillsController可以订阅特定事件,如下所示:

notifier.subscribe($scope, function(event, data) {
    $scope.skills = data;
}, 'onSkillsLoaded');

curriculo服务电话(位于getSkills()notify的末尾,并提供一个事件。在这种情况下,您在SkillsController订阅的事件与<{1}}相同。

notifier.notify('onSkillsLoaded', result);

总而言之,这是我的小榜样背后的魔力。值得一提的是,您需要将最佳实践应用于代码,因为这只是为了重新创建您的场景。对于最佳实践,我建议John Papa Angular Style Guide

更新1

我更新了我的示例以向您显示深层链接。我通过

模拟深层链接
$state.go('.', {area: 2, skill: 5});

这样我可以激活某种状态。现在每个视图都有activate函数。在这个函数中,我做了所有初始化的工作,例如,如果设置了查询参数,则选择区域。如您所知,您可以使用$state服务访问参数。我不得不使用$timeout来延迟区域控制器的初始化,因为订阅还没有完成。请尝试找到解决此问题的更好方法。也许您可以使用promises或在服务中注册每个控制器,如果所有控制器都已初始化,该服务将解析。

如果选择了任何内容,我还会使用go和其他选项将notify设置为false

$state.go('.', {area: area.id, skill: skillId ? skillId : undefined}, {notify: false});

如果notify设置为false,则会阻止控制器重新初始化。因此,您只能更新URL,并且不会发生状态更改。