如何创建复制现有指令的可重用 AngularJs 指令

Posted

技术标签:

【中文标题】如何创建复制现有指令的可重用 AngularJs 指令【英文标题】:How to create reusable AngularJs directives that copy existing directives 【发布时间】:2013-08-09 07:50:18 【问题描述】:

我正在为我们的应用程序中的常用控件创建一些可重用的指令。

例如,我们有一个用于数量文本框的 html 片段

<div class='amount'>
    <input type='text' ng-model='dollars'/>
</div>

从那里我开始创建我的指令:

app.directive("amount", function()
    return 
        restrict: "E",
        template: "<div class='amount'><input type='text'/></div>",
        replace: true
    
);

呈现以下&lt;html/&gt;

<div class="amount ng-pristine ng-valid" ng-model="dollars">
    <input type="text">
</div>

现在ng-model 位于&lt;div/&gt; 上,这不是我想要的,所以我需要创建一个范围并将其附加到ngModel 上,然后一切都恢复了。

app.directive("amount", function()
    return 
        restrict: "E",
        scope:
            ngModel: "="
        ,
        template: "<div class='amount'><input type='text' ng-model='ngModel'/></div>",
        replace: true
    
);

一切正常,但假设我还想添加一个ngChange 指令,这是否意味着我需要再次更改我的scope 以包含ngChange: "="?像这样

app.directive("amount", function()
    return 
        restrict: "E",
        scope:
            ngModel: "=",
            ngChange : "="
        ,
        template: "<div class='amount'><input type='text' ng-model='ngModel'/></div>",
        replace: true
    
);

问题

我是否需要不断修改指令范围以包含我可能需要的无限数量的其他指令?或者有没有办法将&lt;amount/&gt;元素上的指令复制到&lt;div/&gt;而不是&lt;input/&gt;

例如

<amount my-awesome-directive="" ng-disabled="form.$invalid" ng-model="dollarsAndCents" ng-click="aClick()" ng-show="shouldShow()"/>

变成

<div class="amount">
    <input my-awesome-directive="" type="text" ng-disabled="form.$invalid" ng-click="aClick()" ng-show="shouldShow()" ng-model="dollarsAndCents"/>
</div>

在预编译/后编译期间可以做一些事情来复制它们还是我做错了?

更新

我能够通过简单地循环所有属性并使用$compile() 服务来获得一些工作。它确实有效,但这是正确的吗?

app.directive("amount", function ($compile) 
    return 
        restrict: "E",
        template: "<div class='amount'><input type='text' /></div>",
        replace: true,
        compile: function compile(tElement, tAttrs) 
            return function (scope, iElement, iAttrs) 
                var attributes = $(iElement).prop("attributes");
                var $input = $(iElement).find("input");
                $.each(attributes, function ()  //loop over all attributes and copy them to the <input/>
                    if (this.name !== "class") 
                        $input.attr(this.name, this.value);
                    
                );
                $compile($input)(scope);  //compile the input
            ;
        
    ;
);

鉴于以下&lt;html/&gt;,如果您将任何指令添加到&lt;amount/&gt;,它将被复制到&lt;input/&gt;

<div ng-app="app">
        <amount ng-model="dollars" ng-change="changed = 'I Changed!!!'" ng-click="clicked= 'I Clicked It!'" name="amount"></amount>
         <h1>dollars</h1>
         <h2>changed</h2>
         <h3>clicked</h3>
        <input type="button" value="Remove" ng-click="items.splice(items.indexOf(item), 1)"/>
        <hr/>
</div>

updated jsfiddle

【问题讨论】:

这是一篇较旧的帖子,但是除了复制属性和编译之外,您是否找到了另一种方法? 这里的另一种方法:***.com/a/42319665/913845 【参考方案1】:

绑定一个控制器并注入$scope 方便。

.controller('Amount', ['$scope', function($scope) 
    $scope.myMoney = '2';
])

.directive("amount", function()
    restrict: 'EA',
    replace: true,
    controller: 'Amount',
    template: "<div class='amount'><input type='text' ng-model='myMoney'/></div>",
    //Cleaner to include as URL if the partial is bigger.
    //templateUrl: '/views/amount.html',
    link: function(scope, controller) 
);

【讨论】:

好的,如果ng-disabled 在一个实例中是ctrl.isAmountDisabled() 而另一个实例ng-disabled 恰好是ctrl2.isSomeThingElseTrue(),这将如何处理(templateurl 是理想的,但问题很简单) 这似乎也不能解决在&lt;amount super-cool=""/&gt; 上将任意指令复制到&lt;input super-cool=""/&gt; 的问题(除非我遗漏了什么) @Mark 您是否将指令构建为包含它们自己的控制器的模块并将它们注入您的应用程序?还是您正在构建指令并使用应用级控制器来控制逻辑? 理想情况下,我希望指令的***父控制器保存业务逻辑,因此指令本身是愚蠢的。 ` @Mark 您不希望您的应用级控制器控制可重用组件的业务逻辑。理想情况下,您希望能够在“任何”项目中使用此指令。一旦您添加了应用级别控制器的依赖项,它就不再是模块化的。您的数据应该作为另一个模块注入指令模块,由它自己的服务使用,然后传递到它自己的控制器。

以上是关于如何创建复制现有指令的可重用 AngularJs 指令的主要内容,如果未能解决你的问题,请参考以下文章

AngularJS指令中的compile与link函数解析

angularjs指令中的compile与link函数详解补充

火车:重用以前的任务ID

React 中样式化组件的可重用性

Angularjs 类型头指令

AngularJS学习之compile与link函数详解