使用ng-repeat动态加载指令

时间:2015-07-14 09:08:42

标签: javascript html angularjs

我正在包装HTML"选择"我自己的指令元素。该指令应创建一个下拉菜单,表示它的选项。

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

"选项" "选择"中的元素元素用" arBootstrapSelectOption"标记。他们应该有一个"内容" attribute,表示动态指令。应编译此动态指令并在下拉菜单中显示。

基本上,每个选项(由" 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
    }

});
})();

1 个答案:

答案 0 :(得分:0)

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

似乎在高层次上您只想为ng-repeat指定用户提供的模板(例如<ar-country country-id='{{$index}}'>)并将其放在指令提供的模板中(例如{{1}内) 1}})。

将模板作为内容提供,而不是作为属性,将更容易,更便于用户使用。然后,您只需要转换内容。 (我在这里避免使用<li>,因为它本身就是一个指令而且我不明白你想要做什么 - 我将使用<option>代替:

<my-option>

指令看起来像这样:

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

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

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

(指令<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使用require

myOption