Javascript 具有可选属性的角度指令
我有一个自定义的下拉指令,它具有诸如class和ng model等公共属性 我已经决定扩展此控件以支持验证,现在需要包括可选属性,这些属性只有在由程序员设置时才应包含在输出模板中 样本Javascript 具有可选属性的角度指令,javascript,angularjs,angularjs-directive,Javascript,Angularjs,Angularjs Directive,我有一个自定义的下拉指令,它具有诸如class和ng model等公共属性 我已经决定扩展此控件以支持验证,现在需要包括可选属性,这些属性只有在由程序员设置时才应包含在输出模板中 样本 'use strict'; angular.module(APP) .directive('wkKeyLabelSelect', ["$compile", function($compile) { return { restrict: 'EA', repl
'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));
}
}
}
};
}
]);
<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移到了字符串连接中,我在编译指令的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));
}
}
}
};
}
]);
<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>
用于运行指令的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));
}
}
}
};
}
]);
<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>
引入自定义输入控制器的“正确”方法是支持。这使您的自定义控件能够与支持ngModel
的其他指令集成,如自定义验证器、解析器等。这有点棘手,但使您的控件与框架的内置控件无法区分:
.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);
};
}
};
});
这似乎不是你所问问题的答案,但那只是因为你的问题有点像XY问题。通过实现自定义输入控件,您可以实现您开始要做的事情—将name
属性分配给指令(如果提供了表单指令,则该指令会将自身注册到表单指令中),并且ng required
本机工作。但是,如果必须将name
/id
分配给基础
(出于CSS原因或诸如此类的原因),则可以使用ng attr-
有条件地应用属性。模板将更改为:
<select ng-attr-name="attrs.name || undefined"
ng-attr-id ="attrs.id || undefined"
ng-model="inner" ...
为什么您的代码截图与粘贴的代码完全相同?另外,您似乎正在实现一个,但是您应该正确地使用
ngModelController
——执行范围:{ngModel:=“}
是错误的方法。图像用特定的问题注释,指向有问题的代码。这就是为什么它看起来像是重复的,我有代码和带注释的图像。我不知道ngModelController,现在正在对此进行研究。作为对“应该Peropely使用ngModelController”的回应,我做了一些研究,因为我没有做自定义验证或复杂属性,无需引入使用ngModelController的复杂性。我的观点来源是:您正在引入一个自定义输入控件。当然,它在模板中使用了现有的输入控件,但是如果您希望它支持ngModel
模型(即支持其他验证器、自定义解析器、与
集成等),那么最好使用ngModelController
。你不必,但那是最有棱角的方式。总的来说,你问的是一个XY问题——相反,请解释一下你试图通过自定义下拉菜单实现什么,普通的
无法提供。ng attr上的第二秒是一个真正的帮助,我在这里读到了:大多数情况下,我在可选属性方面遇到了问题(@DavidCruwys,可选属性有什么问题?