重新链接现有的$ scope?

时间:2014-05-08 07:49:48

标签: angularjs

让我先说明一些背景; 我正在创建一个角度向导,具有以下特征:

  • 向导中的步骤很大;每一步都有它自己的控制器/ $ scope / template。
  • 向导中的步骤是动态的(步骤1' s输出决定下一步是步骤2a还是步骤2b。)
  • 当然,应保留步态。当从步骤2退回到步骤1时,step1视图中的数据应该仍然存在。

在我的实施中,我在ui-router的代码库中找到了很多灵感。
基本上我的方法是:

  • 进入某个步骤时,为此步骤创建$ scope并使用$ controller服务创建控制器
  • $编译步骤模板并将此步骤模板链接到step- $ scope

这一切都很棒。


但是,我对我的实现有疑问,请回到向导中: 为了达到这个目的,我为每个步骤保留了一系列step-$范围对象。

每当退回时(例如从步骤2回到步骤1),我:

  • 查找step1的$ scope
  • 重新编译step1的模板并将其重新链接到step1的$ scope

然而,这似乎有效:

  1. 为什么我不能重新使用第1步中的编译/链接模板?
    (这样,我可以保留对已编译/链接模板的引用,而不是对$ scopes的引用)
  2. 这是重新编译/重新链接正确的方法吗?


  3. 感谢您的时间,
    柯恩

3 个答案:

答案 0 :(得分:1)

首先,您如何存储数据?对于这种模式,最好的选择是存储步骤数据的服务。这项服务将通过您的所有步骤(控制器)提供。

有关服务的更多信息:https://docs.angularjs.org/guide/services

接下来,您将讨论两种解决方案:

  • 再次存储数据并让角度从头开始构建屏幕
  • 存储完整编译的模板

第一个解决方案是角度标准行为。为了保持尽可能轻量级的DOM,angular会删除以前的ng-view DOM元素,并用新的元素替换它们(新路径)。没问题,这是角度的工作,它做得很好。

第二种解决方案是可能的。在我看来,存储已编译的DOM会有点过分,相反,你可以让它在浏览器中加载(但是通过CSS显示/隐藏其内容)......但是与方法#1(重量级DOM)不同,它有一些缺点。 / p>

我认为你应该只使用存储的数据来构建你的步骤。

答案 1 :(得分:1)

我会使用路由,使用行

$routeProvider
  .when('/wizard/:stepNr', {...})

(c.f.AngularJS docs:https://docs.angularjs.org/api/ngRoute/service/ $ route#example)

你的"回来"和" next"按钮就像这样的一个href:

<a href="#/wizard/{{scopeVarContainingNumberOfPrevStep}}">Prev</a>
<a href="#/wizard/{{scopeVarContainingNumberOfNextStep}}">Next</a>

所有步骤的范围都有一个共同的$ parent。因此,在进行下一步之前,您可以将重要值存储在那里:

$scope.$parent.stepData[currentStepNr] = $scope.stepData;

每当回到某个步骤时,左侧未来步骤的范围将自动销毁。您需要做的就是

$scope.stepData = $scope.$parent.stepData[currentStepNr]; // load from parent scope into current scope
delete $scope.$parent.stepData[currentStepNr]; // discard in the parent scope

PS:父范围对所有步骤范围都是通用的这一事实是一个特殊情况&#34;因此,您可能希望使用服务在步骤之间存储数据,如@Bixi

所示

编辑:如果下一步的数量由外部网络服务决定,你可以做(​​假设一个简单的http呼叫)

$http.get('/your/service').success(function(responseData){
    /* grab nr of next step from responseData; 
       remember it and 
       use $location.$path to navigate to #/wizard/nextStep.  */ 
    $location.$path('/wizard/' + varContainingNumberOfNextStep);
});

答案 2 :(得分:0)

为什么不让父控制器使用某个步骤标志并使用ngInclude功能来创建新的子范围?

mod.controller('WizardParentCtrl', function() {
  this.step = '1';
})

外部HTML:

<div ng-controller="WizardParentCtrl as WizardParent">
  <div ng-include="'steps/'+WizardParent.step+'.html'"></div>
</div>

内部HTML:

<div ng-controller="Step1Ctrl as Step1">
...
</div>
可以通过范围继承在子控制器中访问

WizardParent,您可以与它通信以保存数据或更改步骤。