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

时间:2013-08-07 19:10:20

标签: angularjs angularjs-directive

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

例如,我们有一个用于金额文本框的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
    }
});

其中呈现以下<html/>

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

现在ng-model位于<div/>上,这不是我想要的,所以我需要创建一个范围并将其附加到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
    }
});

问题

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

E.g。

<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
            };
        }
    };
});

如果您向<html/>添加任何指令,则会给出以下<amount/>,并将其复制到<input/>

<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

1 个答案:

答案 0 :(得分:-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) {}
});