[英]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.