[英]Angular Directive with Optional Attributes
I have a custom dropdown directive that has common attributes such as class and ng-model . 我有一个自定义下拉指令,它具有常见的属性,如class和ng-model 。
I have decided to extend this control for support for validation and now need to include optional attributes that should only get included in the output template if they are set by the programmer. 我已决定扩展此控件以支持验证,现在需要包含可选属性,如果它们由程序员设置,则只应包含在输出模板中。
Sample 样品
I have a partially working system in which I moved my code out of a template URL and into a string concatenation which I call in the post: function of the directives compile. 我有一个部分工作的系统,我将代码从模板URL中移出并转换为字符串连接,我在post:函数中指令编译。
I would have preferred to leave my directives HTML in a template, but could not get that working so I have this solution. 我本来希望将我的指令HTML留在模板中,但是无法使其工作,所以我有这个解决方案。
Questions: 问题:
Code for Directive 指令代码
'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));
}
}
}
};
}
]);
Code for Directive Controller 指令控制器代码
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 used to run the directive 用于运行指令的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>
My Original Template URL content, not used currently 我的原始模板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>
The "proper" way to introduce a custom input controller is to support the ngModelController
. 引入自定义输入控制器的“正确”方法是支持
ngModelController
。 This enables your custom control to integrate with other directives that support ngModel
, like custom validators, parsers, <form>
s. 这使您的自定义控件能够与支持
ngModel
其他指令集成,如自定义验证器,解析器, <form>
。 This is a bit tricky, but makes your control indistinguishable from built-in controls for the framework: 这有点棘手,但是使您的控件与框架的内置控件无法区分:
.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);
};
}
};
});
Then, it can neatly integrate with other controls and leverage validators likes ng-required
natively: 然后,它可以与其他控件整齐地集成,并利用本机
ng-required
验证器:
<custom-select name="c1" ng-model="c1" items="items" ng-required="true">
</custom-select>
It may not seem like the answer to the question you asked, but that is only because your question is a bit of an XY question. 这似乎不是你提出的问题的答案,但这只是因为你的问题是一个XY问题。 By implementing a custom input control, you achieve what you set out to do - assign
name
attribute to a directive (which registers itself with the form directive, if it is provided) and ng-required
works natively. 通过实现自定义输入控件,你实现自己为自己设定的事-指定
name
属性的指令(其本身注册形式的指令,如果提供的话)和ng-required
作品本身。 However, if you must assign name
/ id
to the underlying <select>
(for CSS reasons or whatnot), you could use ng-attr-
to conditionally apply an attribute. 但是,如果必须将
name
/ id
分配给基础<select>
(出于CSS原因或诸如此类),则可以使用ng-attr-
有条件地应用属性。 The template would change to: 模板将更改为:
<select ng-attr-name="attrs.name || undefined"
ng-attr-id ="attrs.id || undefined"
ng-model="inner" ...
Of course, you'd need to expose attrs
on the scope in the link function with: 当然,您需要在链接函数中的范围上公开
attrs
:
link: function(scope, element, attrs, ngModel){
scope.attrs = attrs;
// etc...
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.