【问题标题】:AngularJS Upgrade (1.5 to 1.6,1.7) Makes directive scope bindings undefinedAngularJS 升级(1.5 到 1.6,1.7)使指令范围绑定未定义
【发布时间】:2017-07-14 12:57:18
【问题描述】:

我有以下代码:

angular
  .module('myApp')
  .directive('layout', function () {
      return {
          restrict: 'E',
          template: '<div ng-include="layoutCtrl.pageLayout"></div>',
          controller: 'LayoutController',
          controllerAs: 'layoutCtrl',
          bindToController: true,
          scope: {
              pageLayout: '=',
              pageConfiguration: '=',
              isPreview: '='
          }
      };
  });

angular
  .module('myApp')
  .controller('LayoutController', LayoutController);

function LayoutController($scope, LayoutDTO, LayoutPreviewDTO) {
    var self = this;
    self.layoutDTO = LayoutDTO;
    self.layoutPreviewDTO = LayoutPreviewDTO;
    var test = $scope;

    if(self.isPreview)
        self.layoutModel = new self.layoutPreviewDTO(self.pageConfiguration);
    else
        self.layoutModel = new self.layoutDTO(self.pageConfiguration);
}


<div>
    <layout page-layout="ctrl.layoutTemplateUrl" page-configuration="ctrl.pageConfiguration" is-preview="false"></layout>
</div>

在 Angular 1.5.3 版本中,这按预期工作,我的 Controller 中的变量带有值。现在,自从我升级到 1.6.x,self.pageConfiguration 现在是未定义的。

除了 Angular 版本,没有任何变化。

如何处理传入控制器中的指令的值?

【问题讨论】:

  • 您是否检查过 Angular 更改日志中是否存在可能导致此代码“无法工作”的重大更改?究竟什么不起作用 - 你得到什么错误?您是否也将其他 ng 原生模块更新为相同版本的 angular?
  • self.pageConfiguration 现在是“未定义”,而不是我从 html
  • 不幸的是,这太宽泛了。你能制作一个重现这个问题的小提琴吗?因为在不知道如何调用此指令等的情况下很难调试。
  • 问题标签下有一个edit链接 - 点击它并更新答案

标签: angularjs angular-directive angular-controller angularjs-1.6


【解决方案1】:

AngularJS 团队建议将依赖于范围绑定的控制器代码移到 $onInit 函数中。

function LayoutController($scope, LayoutDTO, LayoutPreviewDTO) {
    var self = this;
    this.$onInit = function () {
        // bindings will always be available here
        // regardless of the value of `preAssignBindingsEnabled`.
        self.layoutDTO = LayoutDTO;
        self.layoutPreviewDTO = LayoutPreviewDTO;
        var test = $scope;

        if(self.isPreview)
            self.layoutModel = new self.layoutPreviewDTO(self.pageConfiguration);
        else
            self.layoutModel = new self.layoutDTO(self.pageConfiguration);
    };
}

$编译:

由于bcd0d4,默认情况下禁用控制器实例上的预分配绑定。仍然可以重新打开它,这在迁移过程中应该会有所帮助。预分配绑定已被弃用,并将在未来的版本中删除,因此我们强烈建议您尽快迁移您的应用程序以使其不再依赖它。

依赖于存在绑定的初始化逻辑应该放在控制器的$onInit() 方法中,保证总是在分配绑定之后调用。

-- AngularJS Developer Guide - Migrating from v1.5 to v1.6 - $compile


更新

$compileProvider.preAssignBindingsEnabled 标志已从 AngularJS V1.7 中删除。

AngularJS 团队强烈建议尽快迁移您的应用程序,使其不再依赖它。AngularJS V1.6 将于 2018 年 7 月 1 日结束生命周期。

来自文档:

由于38f8c9,构造函数中不再提供指令绑定。

以前,支持 $compileProvider.preAssignBindingsEnabled 标志。该标志控制绑定是否在控制器构造函数中可用或仅在 $onInit 挂钩中可用。绑定现在在构造函数中不再可用。

要迁移您的代码:

  • 如果您指定了$compileProvider.preAssignBindingsEnabled(true),您需要首先迁移您的代码,以便可以将标志翻转为false"Migrating from 1.5 to 1.6" guide 中提供了有关如何执行此操作的说明。然后,删除 $compileProvider.preAssignBindingsEnabled(true) 语句。

— AngularJS Developer Guide - Migrating to V1.7 - Compile

注意:

2018 年 7 月 1 日,对 AngularJS 1.6 的支持结束。如需更多信息,请参阅AngularJS MISC - Version Support Status

【讨论】:

  • 好的,我会在以后的版本中记住这一点,感谢您将我指向这篇文章
  • @drabbitharv 您应该将此标记为正确答案。
【解决方案2】:

我想通了:

https://github.com/angular/angular.js/commit/dfb8cf6402678206132e5bc603764d21e0f986ef

现在默认为false,必须设置为true $compileProvider.preAssignBindingsEnabled(true);

【讨论】:

  • 如果您尝试遵循迁移路径,这是一个坏主意,因为所做的只是将其切换回 1.5。正如@georgeawg 提到的,您应该使用 $onInit() 来更正您的绑定
  • $compileProvider.preAssignBindingsEnabled 标志已从 AngularJS V1.7 中删除。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-14
  • 1970-01-01
  • 2014-07-30
相关资源
最近更新 更多