2016-04-22 74 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>