在AngularJS中动态添加指令

时间:2015-01-16 11:35:39

标签: javascript angularjs

我在使用指令时遇到一些问题,我希望在用户点击按钮时动态添加该指令。实现这一目标的最佳方法是什么?

在我的研究中,我发现element.bind(来自jqLit​​e),但我在互联网上找不到很多例子。

这是我的代码:


HTML CODE

<div class="form-group">
    <button class="btn btn-info" ng-click="addAttr()">Add Atributtes</button>
</div>
<addattributes options="attributes" attr="obj"></addattributes>

<小时/> ANGULARJS DIRECTIVE

.directive('addattributes', function () {
return {
    restrict: 'E',
    scope: {
        attributes: '=options',
        attr: '='
    },
    template: 
    '<div ng-class="classInput">' +
    '   <div class="col-md-8" style="padding-left: 0;">' +
    '       <label>Nome do Atributo</label>' +
    '       <input type="text" class="form-control" placeholder="Attrs name" ng-model="attrname" ng-change="validation()">' +
    '   </div>' +
    '   <div class="col-md-4" style="padding-right: 0;"> ' +
    '       <label>Tipo do Atributo</label> ' +
    '           <select class="form-control" ng-options="attribute.name for attribute in attributes" ng-model="attrtype"></select>' +
    '   </div> '+
    '   <div class="clearfix"> '+
    '   <div> '+
    '   <button type="button" class="btn btn-default btn-xs pull-right" ng-click="changeButton()" style="margin-top: 1em;" ng-show="showBtn == true"> Adicionar </button>       ' +
    '   </div> {{attr}}'+
    '</div>',
    link: function(scope,element,attrs){
        scope.showBtn = true;
        scope.classInput = 'form-group';
        scope.attrtype= scope.attributes[2];

        scope.changeButton = function(){
            scope.showBtn = false;
            scope.attr = {
                name: scope.attrname,
                type: scope.attrtype
            };
        }

        scope.validation = function(){
            if(scope.attrname.length < 6) {
                scope.classInput = 'form-group has-error';
            } else {
                scope.classInput = 'form-group has-success';
            }
        }


    }
};})

提前致谢,祝你有美好的一天!

2 个答案:

答案 0 :(得分:2)

您没有在控制器中“添加指令”。这意味着你正在操纵DOM,你不应该这样做。

相反,请考虑ViewModel。该指令显示/更改的ViewModel属性是什么?假设它是一个“属性”,所以将attribute添加到$scope.myAttributes(以避免与您拥有的某些attributes属性名称冲突)。

$scope.myAttributes = [];
$scope.addAttr = function(){
   $scope.myAttributes.push({}); // empty object to hold some property of an "attribute"
}

然后,在视图中,ng-repeat超过attributes

<div class="form-group">
    <button class="btn btn-info" ng-click="addAttr()">Add Atributtes</button>
</div>
<addattributes ng-repeat="attribute in myAttributes" attr="attribute"></addattributes>

(我不完全理解你的addattributes指令的作用,所以我假设它通过attr设置属性对象。)

答案 1 :(得分:1)

如果不提供有关用例的详细信息,很难说明您尝试实现的内容是否可以通过ng-show更简单(更重要的是更直观)完成,{ {1}}或其他ng-switch指令,但我们假设您的方法经过深思熟虑。

正如@New Dev已经在另一个答案中指出的那样,你应该尝试将DOM操作保留在指令中,而不是在控制器中 - 这将有助于可测试性,关注点分离以及许多其他事情。 / p>

以下代码演示了如何执行您尝试执行的操作,但是以抽象的方式,因为您的示例看起来太复杂而无法进行简单的回答。


如果您的指令是名为ng-的元素,则添加它是一个三步过程:

  1. 创建元素并将其附加到DOM
  2. 编译元素
  3. 将其链接到范围
  4. 您应该在可以访问元素的指令的链接功能中执行此操作:

    newDirective

    请注意,指令的link: function (scope, element, attributes) { scope.addDirective = function () { // create the new directive element $newDirective = angular.element('<new-directive>'); // Append it to the DOM element.append($newDirective); // compile it and link it to the scope $compile($newDirective)(scope); } } 函数返回其链接函数,因此编译&amp;链接实际上是一行中的两个步骤。

    请参阅下面的runnable代码段。 compile添加了myDirective个。 newDirective的模板包含一个删除它的按钮。单击“删除”按钮有效,证明链接功能已运行且指令正常运行。

    &#13;
    &#13;
    newDirective
    &#13;
    angular.module('app', [])
    .directive('myDirective', function ( $compile ){
      return {
        restrict: 'E',
        template: '<button ng-click="addDirective()">Click me!</button>',
        link: function (scope, element, attributes) {    
          scope.addDirective = function () {
            // create the new directive element
            $newDirective = angular.element('<new-directive>');
            // Append it to the DOM
            element.append($newDirective);
            // compile it and link it to the scope
            $compile( $newDirective )(scope);
          }
        
        }
      }
    })
    .directive('newDirective', function ( $compile ){
      return {
        restrict: 'E',
        template: '<li>{{someText}}' +
          '<button ng-click="remove()">Remove</button>' +
        '</li>',
        link: function (scope, element, attributes) {  
          scope.someText = "If the scope is linked this will show";
          scope.remove = function () {
            element.remove() 
          }
        }
      }
    });
    &#13;
    &#13;
    &#13;