[英]Angular Directive with Optional Attributes
我有一個自定義下拉指令,它具有常見的屬性,如class和ng-model 。
我已決定擴展此控件以支持驗證,現在需要包含可選屬性,如果它們由程序員設置,則只應包含在輸出模板中。
樣品
我有一個部分工作的系統,我將代碼從模板URL中移出並轉換為字符串連接,我在post:函數中指令編譯。
我本來希望將我的指令HTML留在模板中,但是無法使其工作,所以我有這個解決方案。
問題:
指令代碼
'use strict';
angular.module(APP)
.directive('wkKeyLabelSelect', ["$compile",
function($compile) {
return {
restrict: 'EA',
replace: true,
scope: {
'class': '@', // Permanent - One Way Attribute
ngModel: '=', // Permanent - Two Way Attribute (Angular)
items: '=', // Permanent - Two Way Attribute (Custom)
id: '@', // Dynamic - One Way Attribute
name: '@', // Dynamic - One Way Attribute
ngRequired: '=', // Dynamic - Two Way Attribute (Angular)
},
//templateUrl: COMPONENTS_PATH + '/keyLabelSelect/keyLabelSelect.html',
controller: 'KeyLabelSelectController',
link: function (scope, element, attrs) {
//$compile(element)(scope);
},
compile: function (element, attrs) {
// name & ngRequired are not available in the compile scope
//element.replaceWith($compile(html)(scope));
return {
pre: function preLink(scope, iElement, iAttrs, controller) {
},
post: function postLink(scope, iElement, iAttrs, controller) {
// Template goes here
var html =
'<select ' +
' class="{{class}}"' +
(scope.id ? ' id="{{id}}"' : "") +
(scope.name ? ' name="{{name}}"' : "") +
(scope.ngRequired ? ' ng-required="true"' : "") +
' ng-model="ngModel"' +
' ng-options="item.key as item.label for item in items"' +
'>' +
'</select>';
iElement.replaceWith($compile(html)(scope));
}
}
}
};
}
]);
指令控制器代碼
angular.module(APP)
.controller('KeyLabelSelectController', ['$scope', function ($scope) {
$scope.klass = typeof $scope.klass === 'undefined' ? 'form-control' : $scope.klass;
console.log($scope.ngModel);
console.log($scope.items);
}]);
用於運行指令的HTML
<div class="form-group" ng-class="{ 'has-error': editForm.state.$touched && editForm.name.$invalid }">
<label class="col-md-3 control-label">State</label>
<div class="col-md-9">
<wk-key-label-select id="state" name="state"
ng-required="true"
ng-model="model.entity.state"
class="form-control input-sm"
items="model.lookups.job_state">
</wk-key-label-select>
<div class="help-block" ng-messages="editForm.state.$error">
<p ng-message="required">Job State is required.</p>
</div>
</div>
</div>
我的原始模板URL內容,當前未使用
<!-- This is now deprecated in place of inline string -->
<!-- How could I use a in place of string concatenation -->
<select class="{{klass}}"
name="{{name}}"
ng-model="ngModel"
ng-options="item.key as item.label for item in items"></select>
引入自定義輸入控制器的“正確”方法是支持ngModelController
。 這使您的自定義控件能夠與支持ngModel
其他指令集成,如自定義驗證器,解析器, <form>
。 這有點棘手,但是使您的控件與框架的內置控件無法區分:
.directive("customSelect", function() {
return {
require: "?ngModel",
scope: {
itemsExp: "&items" // avoids the extra $watcher of "="
},
template: '<select ng-model="inner" \
ng-options="item.key as item.label for item in itemsExp()"\
ng-change="onChange()"></select>',
link: function(scope, element, attrs, ngModel) {
if (!ngModel) return;
// invoked when model changes
ngModel.$render = function() {
scope.inner = ngModel.$modelValue;
};
scope.onChange = function() {
ngModel.$setViewValue(scope.inner);
};
}
};
});
然后,它可以與其他控件整齊地集成,並利用本機ng-required
驗證器:
<custom-select name="c1" ng-model="c1" items="items" ng-required="true">
</custom-select>
這似乎不是你提出的問題的答案,但這只是因為你的問題是一個XY問題。 通過實現自定義輸入控件,你實現自己為自己設定的事-指定name
屬性的指令(其本身注冊形式的指令,如果提供的話)和ng-required
作品本身。 但是,如果必須將name
/ id
分配給基礎<select>
(出於CSS原因或諸如此類),則可以使用ng-attr-
有條件地應用屬性。 模板將更改為:
<select ng-attr-name="attrs.name || undefined"
ng-attr-id ="attrs.id || undefined"
ng-model="inner" ...
當然,您需要在鏈接函數中的范圍上公開attrs
:
link: function(scope, element, attrs, ngModel){
scope.attrs = attrs;
// etc...
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.