带有 bindToController 的指令无法从子指令中获取数据

directive with bindToController can't get data from child directives

我正在尝试编写一个指令,该指令从其子指令的输入构建一个对象并将其推送 到作为参数提供的数组。类似于:

<aggregate-input on="SiteContent.data.objList">
    <p aggregate-question>Question text</p>
    <input aggregate-answer ng-model="answer" type="text" />
</aggregate-input>
<aggregate-input on="SiteContent.data.objList">
    <p aggregate-question>Question text 2</p>
    <input aggregate-answer ng-model="answer" type="text" />
</aggregate-input>

我希望收集如下数据:

SiteContent.data.objList === [
    {question: 'Quesion text', answer: 'user input'},
    {question: 'Quesion text 2', answer: 'user input 2'},
];

这是 plunker with the code

我无法确定这些指令的通信方式。我期待 input link 中定义的对象将在每个指令的范围内被隔离并推送到 on 对象 假如。结果是 input 对象在所有实例之间共享,只有一个对象得到 曾被推入数组。

我猜被嵌入的范围规则让我感到困惑,但我真的不知道在哪里。有任何想法吗?谢谢!

第一个问题:您的 aggregate-input 指令指定了一个没有绑定属性的隔离范围,但您仍然在带有指令的元素上使用 on 属性:

<aggregate-input on="SiteContent.data.objList">

但是在你的 JS 中,

{
    restrict: 'E',
    scope: {},
    controller: aggregateInputController,
    controllerAs: 'Aggregate',
    bindToController: { on: '=' },
    /* */
}

而你需要的是

{
    restrict: 'E',
    scope: { on: '=' },
    controller: aggregateInputController,
    controllerAs: 'Aggregate',
    bindToController: true // BOOLEAN REQUIRED HERE, NO OBJECT
}

根据 the spec 关于 bindToController 的段落,

When an isolate scope is used for a component (see above), and controllerAs is used, bindToController: true will allow a component to have its properties bound to the controller, rather than to scope. When the controller is instantiated, the initial values of the isolate scope bindings are already available.

那么你就不需要将on 属性分配给你的控制器了,它是由Angular为你完成的(我也不明白你为什么这样做this.on = this.on || []this.on || 部分对我来说似乎没有必要)。

我想您可以将其应用于其余代码,这应该是一个开始。我要寻找更多问题。

编辑: 我发现的其他几个问题:

  • 如果 siteContent 的作用域被隔离,那么当编译指令时 SiteContent 控制器不可访问并且 Angular 静默失败(就像总是.. .) 在评估 SiteContent.data.objList 以将其传递给子指令时。我通过从定义中删除 scope: {} 来解决这个问题。

  • 有必要将 aggregateInputLink 的功能移至 aggregateInputController,因为像往常一样,子控制器在 link 函数之前执行,并且由于aggregateQuestion 指令在其 控制器 中调用 InputCtrl.changeValue('question', elem.text());,在父指令 post-[=74 中分配给 scope.input =]函数还不存在。

function aggregateInputController($scope) {
    $scope.input = {};
    this.on.push($scope.input);

    this.changeValue = function changeValue(field, value) {
        $scope.input[field] = value;
    };
}

提醒一下:在遍历指令树期间,控制器以预序方式执行,link 以 post 方式运行。

  • 最后,在那之后,SiteContent 控制器的数据没有得到呈现 属性 因为在 ng-repeat 中用于迭代的集合被错误地 SiteContent.objList 而不是 SiteContent.data.objList.

Link 到最终 plunker