【问题标题】:Dynamic controller for directives with ECMA6ECMA6 指令的动态控制器
【发布时间】:2016-03-17 18:14:35
【问题描述】:

我正在尝试使用name 属性为我的指令动态设置控制器。到目前为止,这是我的代码。

html

<view-edit controller-name="vm.controller" view="home/views/med.search.results.detail.resources.audios.html" edit="home/views/med.media.resources.edit.html"></view-edit>

js

export default class SearchResultsCtrl extends Pageable {

  /*@ngInject*/
  constructor($injector, $state, api) {

    super(
      {
        injector: $injector,
        endpoint: 'mediaMaterialsList',
        selectable:{
          itemKey: 'cid',
          enabled:true,
          params: $state.params
        },
        executeGet: false
      }
    );

    this.controller = SearchResultsResourcesAudiosCtrl;
  }
}

指令

export default class ViewEditDirective {

  constructor() {
    this.restrict = 'E';
    this.replace = true;
    this.templateUrl = 'home/views/med.view.edit.html';
    this.scope = {};
    this.controller = "@";
    this.name = "controllerName";
    this.bindToController = {
      'view': '@?',
      'edit': '@?'
    };

    this.open = false;
    this.controllerAs = 'ctrl';
  }
}

我得到undefinedvm.controller。我猜它是在控制器将控制器分配给变量之前渲染的(我调试了它,它在变量中设置了控制器)。

我正在遵循这个答案来实现这一目标,但到目前为止还没有运气。 How to set the dynamic controller for directives?

谢谢。

【问题讨论】:

    标签: javascript angularjs angularjs-directive ecmascript-6


    【解决方案1】:

    这个问题与 ES6 无关(它是 ES5 的糖语法涂层),这就是 Angular 范围生命周期的工作原理。

    该指令可能显示属性插值的处理方式

    // <div ng-init="a = 1"><div sum="{{ a + 1 }}"></div></div>
    app.directive('sum', function () {
      return {
        scope: {},
        controller: function ($attrs) {
          console.log($attrs.sum) // {{ a + 1 }}
          // ...
        },
        link: function (scope, element, attrs) {
          console.log(attrs.sum) // 2
        }
      };
    });
    

    如果在此之后设置了a 值(即在父指令link 中),则$attrs.sum 可能仍然不是link 中的2

    假设某个作用域上的值可以在某个时间点基于另一个作用域的值来计算是不安全的(并且本身就是错误的)。因为它可能不是。这就是观察者和数据绑定存在的原因。

    所有controller: '@' 魔法值所做的就是获取uninterpolated attribute value 并将其用作控制器名称。所以不,它不会从 vm.controller 插入控制器名称,而是使用 'vm.controller' 字符串作为控制器名称。

    允许动态设置其控制器的指令示例可能如下所示

    // dynamic-controller="{{ ctrlNameVariable }}"
    app.directive('dynamicController', function () {
        return {
            restrict: 'A',
            priority: 2500,
            controller: function ($scope, $element, $attrs, $interpolate, $compile) {
                var ctrlName = $interpolate($attrs.dynamicController)($scope);
    
                setController(ctrlName);
                $attrs.$observe('dynamicController', setController);
    
                function setController (ctrlName) {
                    if (!ctrlName || $attrs.ngController === ctrlName) {
                        return;
                    }
    
                    $attrs.$set('ngController', ctrlName);
                    $compile($element)($scope);
                }
            }
        };
    });
    

    具有重新编译可能带来的所有副作用。

    【讨论】:

    • 嗨!非常感谢您的回答,我明天一到办公室就试试这个。另一个问题。如果我直接传递控制器的名称,我不需要插值,对吧?喜欢做&lt;view-edit controller-name="SearchResultsResourcesAudiosCtrl" view="home/views/med.search.results.detail.resources.audios.html" edit="home/views/med.media.resources.edit.html"&gt;&lt;/view-edit&gt;
    • @LukeSpringWalker 是的,这应该按原样工作,这就是controller: '@' 的目的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-26
    • 2015-03-17
    • 2014-04-09
    • 2013-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多