【问题标题】:Load directives dynamically using ng-repeat使用 ng-repeat 动态加载指令
【发布时间】:2015-07-15 15:20:34
【问题描述】:

我正在用我自己的指令包装 HTML“选择”元素。这个指令应该创建一个下拉菜单来代表它的选项。

我用我的自定义“arBootstrapSelect”指令/属性标记选择元素。 该指令附加一个下拉菜单,其中包含由 ng-repeat 重复的选项。

“select”元素中的“option”元素被标记为“arBootstrapSelectOption”。它们应该有一个“内容”属性,代表一个动态指令。这个动态指令应该被编译并显示在下拉菜单中。

基本上,每个选项(由“arBootstrapSelectOption”标记)使用 $compile 服务编译它的“内容”属性,并将其注入到 arBootstrapSelect 指令中的列表中。之后 arBootstrapSelect 应该使用 ng-repeat 显示已编译的选项。希望不要太复杂。 我收到Error Link

HTML:

<select ar-bootstrap-select class="form-control">
                <option ar-bootstrap-select-option value={{$index}} ng-repeat="c in countries" content="<ar-country country-id='{{$index}}'></ar-country>">


                </option>
            </select>


<div class="dropdown">
                <button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
                    Dropdown
                    <span class="caret"></span>
                </button>
                <ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
                    <li ng-repeat="option in arBootstrapSelectOptions">
                        {{option[1]}}
                    </li>
                </ul>
            </div>

我的指令:

(function () {
'use strict';
var app = angular.module('mainApp');

app.directive('arBootstrapSelect', function ($interval, $compile) {
    $scope.arBootstrapSelectOptions = [];

    function link(scope, element, attrs) {
        //element.hide();

    }

    return {
        restrict: 'A',
        link: link,
        scope: true
    }

});

app.directive('arBootstrapSelectOption', function ($compile) {
    function link(scope, element, attrs) {
        scope.arBootstrapSelectOptions.push([attrs.value, $compile(attrs.content)(scope)]);
    }

    return {
        scope: true,
        restrict: 'A',
        link: link,
    }

});
})();

这可行,但它又丑又慢:

(function () {
'use strict';
var app = angular.module('mainApp');

app.directive('arBootstrapSelect', function ($interval, $compile) {
    //$scope.arBootstrapSelectOptions = [];

    function link(scope, element, attrs) {
        //element.hide();

        scope.$on('arBootstrapSelectNewItem', function (event, data) {
            var test = $('<li></li>').append(data);
            element.parent().find('.dropdown-menu').append(test);

        });

    }

    return {
        restrict: 'A',
        link: link,
        scope: true,
        transclude: true
    }

});

app.directive('arBootstrapSelectOption', function ($compile) {
    function link(scope, element, attrs) {
        //scope.arBootstrapSelectOptions.push([attrs.value, $compile(attrs.content)(scope)]);
        scope.$emit('arBootstrapSelectNewItem', $compile(attrs.content)(scope));

    }

    return {
        scope: true,
        restrict: 'A',
        link: link
    }

});
})();

【问题讨论】:

  • 您是否尝试用自定义选择替换/增加&lt;select&gt;?对于这个问题,&lt;select&gt; 重要吗?如果没有,你能减少这个例子吗?我建议删除不相关的所有内容(样式、控件、标记)。举例说明您希望最终结果的样子。此外,该错误似乎与插值有关 - 您确定它在您发布的代码中吗(例如,不在 arCountry 指令中)?
  • 底线,我正在编译一个指令并将它的编译状态存储在一个列表中。如何使用 ng-repeat 加载它?
  • 再说一遍,太宽泛了。我可以尝试为您提供 a 解决方案,但在不了解您的确切问题的情况下,它可能会离题。和。准确地说,您正在存储一个编译和链接的元素。一旦你有了元素,你就可以迭代并将它们放置在 DOM 中——当然,这将不必要地重新创建 ng-repeat 正在做的事情

标签: javascript html angularjs


【解决方案1】:

我不完全理解你的具体例子,所以我会从概念层面回答。

您似乎想要在较高级别上为ng-repeat 指定用户提供的模板(例如&lt;ar-country country-id='{{$index}}'&gt;)并将其放置在指令提供的模板中(例如在&lt;li&gt; 中)。

将模板作为内容而不是作为属性来提供会更容易,对用户也更友好。然后,您所需要的就是嵌入内容。 (我在这里避免使用&lt;option&gt;,因为它本身就是一个指令,我不完全理解您要做什么 - 我将使用&lt;my-option&gt; 代替):

<my-option ng-repeat="c in countries">
  <ar-country country-id='{{$index}}'></ar-country>
<my-option>

指令看起来像这样:

.directive("myOption", function(){
  return {
    scope: true,
    transclude: true,
    template: '<li ng-transclude></li>'
  }
});

这将在概念上创建以下 HTML:

<my-option>
  <li><ar-country country-id="0"></ar-country></li>
</my-option>
<my-option>
  <li><ar-country country-id="1"></ar-country></li>
</my-option>
..

(指令arCountry也会被编译链接,可能会生成自己的内容)

另外,如果家长需要给每个孩子注册,最好用require交流,而不是$emit/$on。所以,parent 需要定义一个具有注册子功能的控制器。同样,如果您需要提供额外的模板,请嵌入内容:

<my-select>
  <my-option ng-repeat="c in countries>
    <ar-country country-id='{{$index}}'></ar-country>
  </my-option>
</my-select>
.directive("mySelect", function(){
  return {
    scope: true,
    transclude: true,
    template: '<h1>heading</h1><div ng-transclude></div>',
    controller: function(){
      // this can be called by the child
      this.registerChild = function(childElement, childController){
        // store the children, if needed
      }
    }
  }
});

要使用this.registerChild,我们需要让myOption使用require

.directive("myOption", function(){
  return {
    scope: true,
    transclude: true,
    template: '<li ng-transclude></li>'
    require: ['myOption', '^mySelect'],
    controller: function(){
      // you can define some functions here
    },
    link: function(scope, element, attrs, ctrls){
      var me = ctrls[0], 
          selectCtrl = ctrls[1];

      selectCtrl.registerChild(element, me);
  }
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-22
    • 1970-01-01
    • 2014-11-07
    • 1970-01-01
    • 2017-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多