【问题标题】:Custom directive with ng-repeat as transcluded content以 ng-repeat 作为嵌入内容的自定义指令
【发布时间】:2015-11-25 14:24:49
【问题描述】:

我正在处理一个包含multiselect jQuery plugin 的指令。我的目标是将以下 HTML 转换为动态多选:

<select multiselect multiple ng-model="selected">
    <option>Static option 1</option>
    <option>Static option 2</option>
    <option ng-repeat="value in values">{{value}}</option>
</select>

请注意,可以直接添加选项,也可以使用 ng-repeat 迭代动态选项。

这是我编写指令的方式:

app.directive('multiselect', function () {
    return {
        restrict: 'A',
        scope: {
            model: '='
        },
        transclude: true,
        require: 'ngModel',
        link: function (scope, element, attrs, controller, transclude) {
            transclude(function (clone) {
                element.append(clone);
                $(element).multiselect();
            });
        }
    };
});

问题在于,虽然该指令有效并用 jQuery 多选插件替换 HTML,但它只显示静态提供的选项。插件不会显示使用 ng-repeat 创建的选项,即使它们可以在 Angular 呈现的 HTML 源代码中看到。插件创建多选后,似乎将 transclude 克隆附加到元素。

Here's the JSFiddle 重现了这个问题。

我的理解正确吗?这种行为的原因可能是什么?

【问题讨论】:

  • 看起来克隆中的角度需要在附加到元素后进行评估。如果您在 multiselect() 上设置超时(不是一个好的解决方案,但会显示问题),则会显示动态选项。我认为在 transclude 功能(主要是多选部分)完成或暂停之前不会生成动态选项。
  • 谢谢,说得好。我将对此进行进一步评估,并希望找到所需的解决方案。

标签: javascript jquery angularjs angularjs-directive


【解决方案1】:

我不确定为什么你的方法不起作用,但是用 ngOptions 替换 option tag + ngRepeat 似乎可以解决问题。

<select multiselect multiple ng-model="selected" ng-options="value for value in values">
  <option>Static option 1</option>
  <option>Static option 2</option>  
</select>

Working JSFiddle

【讨论】:

  • 这可能比尝试手动添加新方法更好。我可以想象当 Angular 尝试添加一个模棱两可的元素作为 Select 的子元素时会发生某种冲突,而不是你的方式,它的目的非常具体。
  • 结果还是一样,还是缺少控制器提供的动态选项。选择中应该有 5 个选项可用。
  • 5 个选项是我在小提琴中看到的。控制台有什么错误吗?
  • @yarons 在你的 firefox 上使用我只看到静态选项
  • Chrome 和 Firefox 之间似乎存在差异。 Chrome完全不显示插件,FF显示正确,但缺少动态选项。
【解决方案2】:

对于遇到相同问题的任何人,这里有一个完整的链接功能,我使用它并获得了成功的结果。

link: function (scope, element, attrs, controller, transclude) {
  transclude(function (clone) {
    element.append(clone);
  });
  $timeout(function() {
    element.multiselect();
  });
}

别忘了在指令中注入$timeout

.directive('multiselect', function ($timeout) {

transclude 函数负责附加由 ng-repeat 指令生成的内容。但是,ng-options 指令也可以工作,在这种情况下,动态选项会显示在静态选项之前。仅使用 $timeout 包装多选。

我也开始挖掘以了解为什么使用超时功能实际上会有所帮助,并在 John Resig 的 this answerthis blog post 中找到一些合理的解释。

【讨论】:

    猜你喜欢
    • 2013-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-26
    • 1970-01-01
    • 1970-01-01
    • 2015-03-06
    相关资源
    最近更新 更多