2016-04-22 76 views
1

我知道如何通过我的自定义指令传递指令,例如:通行证通过适用指令定制指令

page.html中

<my-directive read-only-attr="myVariable" label-style-attr="anotherVariable"></my-directive> 

指令

myApp.directive("myDirective", function() { 
    return { 
    restrict: "E", 
    templateUrl: "myTemplate.html", 
    scope: { 
     readOnlyScopeVar: "=readOnlyAttr", 
     styleScopeVar: "=labelStyleAttr" 
    }, 
    link: function (scope, element, attrs) { 

    } 
    }; 
}); 

模板

<div> 
    <label ng-style="styleScopeVar" /> 
    <input type="text" ng-readonly="readOnlyScopeVar" /> 
</div> 

我的模板比这个复杂得多,但我简化了它的问题。

我的问题是:如果用户没有在我的指令中指定“只读attr”或“label-style-attr”,我该如何防止ngReadonly和ngStyle运行?有大量的常见的角度指令,我想让人们适用于输入和模板内的其他元素(ngClass,ngDisabled,ngChange,ngPattern,ngIf等),但我不想全部运行它们,如果人没有在我的指令中指定他们。这就好像我需要一个模板来构建模板。

另外,请注意,我已阅读了有关transclusion的内容,但我不喜欢允许用户直接编辑输入元素的想法,并且在此示例中我可能想要应用诸如此类的多个元素如果只读attr引用为true,则可以更改标签颜色。

回答

0

这样做的一种方法是使用$ compile。这里有一个工作plnkr: https://plnkr.co/edit/S8pUSH?p=preview 注意有很多方法可以做到这一点,而这一次是为了演示只是一个简单的例子:

var app = angular.module('app', []); //define the module 

//setup the template 
app.run(['$templateCache', function($templateCache){ 
    $templateCache.put('someDirectiveTmpl','<div>\ 
    <label $$%%ngStylePlaceholder$$%% />My Label:</label>\ 
    <input type="text" $$%%ngReadonlyPlaceholder$$%% />\ 
</div>'); 
}]) 

/** 
* @description someDirective gets a config object that holds dynamic directives' names and values. e.g.: 
* { 
* 'ngStyle': '{background: red;}', 
* 'ngReadonly': true 
* } 
* 
*/ 
app.directive('someDirective', ['$log', '$compile', '$templateCache', function($log, $compile, $templateCache){ 
    return { 
    restrict: 'AE', 
    controllerAs: 'someDirectiveCtrl', 
    scope: {}, 
    bindToController: { 
     directiveConfig: '=' 
    }, 
    controller: function($scope, $element){ 
     // a method to convert camelcase to dash 
     function camelCaseToDash(myStr) { 
     return myStr.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase(); 
     } 
// get the template 
     var template = $templateCache.get('someDirectiveTmpl'); 
     var placeHolderRegExp = /\$\$%%(.*)\$\$%%/g; 
     // place the binding per existing property 
     angular.forEach(this.directiveConfig, function(varName, key){ 
     template = template.replace('$$%%' + key + 'Placeholder$$%%', camelCaseToDash(key) + '="someDirectiveCtrl.directiveConfig.' + key + '"'); 
     }); 

     // remove unneeded properties placeholders 
     template.replace(placeHolderRegExp, ''); 

     //compile the directive 
     var templateElement = angular.element(template); 
     $compile(templateElement)($scope); 
// append to element 
     $element.append(templateElement); 

    } 
    } 
}]); 

注意$$%%ngAnythingPlaceholder$$%%在模板中。我从父指令获取配置(在plnkr中,为了简单起见,我使用了一个控制器)。我在示例中使用了一个配置对象(可以使用单独的变量来完成此操作,但我喜欢设置一个配置对象API)。 然后我根据配置中的内容替换占位符,并删除我不需要的东西。然后我编译模板。 在父指令的控制器,你可以不喜欢我在控制器那样:

$scope.config = { 
    ngReadonly: true 
    } 

此外,我注意到你不应该使用一个控制器,当然,不 使用$scope本身,而是指令的控制者的this。我只使用 $scope和控制器,以方便演示。

你可以添加任何你想要的配置(当然,添加占位符到模板中的各种参数)。 现在只需将该指令添加到您的模板中:

<some-directive directive-config="config"></some-directive>