Angularjs 在指令中包装输入
我的想法是将输入打包成自定义指令,以确保整个站点的外观和行为一致。我还想包装引导ui的日期选择器和下拉列表。此外,该指令还应处理验证和显示工具提示 HTML应该如下所示:Angularjs 在指令中包装输入,angularjs,angularjs-directive,angular-ui-bootstrap,Angularjs,Angularjs Directive,Angular Ui Bootstrap,我的想法是将输入打包成自定义指令,以确保整个站点的外观和行为一致。我还想包装引导ui的日期选择器和下拉列表。此外,该指令还应处理验证和显示工具提示 HTML应该如下所示: <my-input required max-length='5' model='text' placeholder='text' name='text'/> 或 在指令中,我想创建一个dom结构,如: <div> <div>..</div> //display va
<my-input required max-length='5' model='text' placeholder='text' name='text'/>
或
在指令中,我想创建一个dom结构,如:
<div>
<div>..</div> //display validation in here
<div>..</div> //add button to toggle datepicker (or other stuff) in here
<div>..</div> //add input field in here
</div>
.. //在此处显示验证
.. //添加按钮切换日期选择器(或其他东西)在这里
.. //在此处添加输入字段
我尝试了各种方法来实现这一点,但总是遇到一些权衡:
目前我正在使用第二种方法,并在link函数中生成模板,但我想知道是否有人有更好的想法 为什么不这样做呢
myApp.directive('wrapForm', function(){
return {
restrict: 'AC',
link: function(scope, inputElement, attributes){
var overallWrap = angular.element('<div />');
var validation = angular.element('<div />').appendTo(overallWrap);
var button = angular.element('<div />').appendTo(overallWrap);
var inputWrap = angular.element('<div />').appendTo(overallWrap);
overallWrap.insertBefore(inputElement);
inputElement.appendTo(inputWrap);
inputElement.on('keyup', function(){
if (inputElement.val()) {
validation.text('Just empty fields are valid!');
} else {
validation.text('');
}
});
}
}
});
myApp.directive('wrapForm',function(){
返回{
限制:“AC”,
链接:函数(作用域、inputElement、属性){
var overallWrap=角度元素(“”);
var验证=角度元素(“”).appendTo(整体包裹);
var按钮=角度元素(“”).appendTo(整体包裹);
var inputWrap=angular.element(“”).appendTo(overallWrap);
整体包裹。插入前(inputElement);
inputElement.appendTo(inputWrap);
inputElement.on('keyup',function()){
if(inputElement.val()){
text('只有空字段有效!');
}否则{
验证。文本(“”);
}
});
}
}
});
小提琴:
基本上,您使用原始输入字段(顺便说一句,它是)并分别构建包装。在本例中,我只是手动构建div。对于更复杂的内容,您还可以使用angularjs获取$compile
(d)的模板
使用这个类或html属性“wrapForm”的好处是:您可以对几种表单输入类型使用相同的指令。以下是我认为正确的方法。像OP一样,我希望能够使用attribute指令包装
输入
。但我也希望它能够在不泄漏任何元素的情况下使用ngif
等。正如@jantimon所指出的,如果不清理包装器元素,那么如果破坏了原始元素,它们将在ng之后徘徊
app.directive("checkboxWrapper", [function() {
return {
restrict: "A",
link: function(scope, element, attrs, ctrl, transclude) {
var wrapper = angular.element('<div class="wrapper">This input is wrappered</div>');
element.after(wrapper);
wrapper.prepend(element);
scope.$on("$destroy", function() {
wrapper.after(element);
wrapper.remove();
});
}
};
}
]);
app.directive(“checkboxWrapper”,[function(){
返回{
限制:“A”,
链接:函数(范围、元素、属性、ctrl、transclude){
var wrapper=angular.element('此输入已包装');
元素。之后(包装器);
wrapper.prepend(元素);
作用域:$on(“$destroy”,函数(){
包装器。在(元素)之后;
wrapper.remove();
});
}
};
}
]);
你可以和我一起玩
重要:
范围
vs元素
$destroy。您必须将清理放在范围内(“$destroy”)
,而不是元素中(“$destroy”)
(这是我最初尝试的)。如果在后一个元素中执行此操作,则“ngIf end”注释标记将被泄漏。这是由于Angular的ngIf在执行错误逻辑时如何清理其结束注释标记。通过将指令的清理代码放在$destroy范围内,您可以像包装输入之前一样将DOM放回原处,因此ng if的清理代码是令人满意的。在调用element.on(“$destroy”)时,如果错误地打开原始元素而不导致注释标记泄漏,则ng if flow中的时间就太晚了。为什么不在编译函数中包装输入?
优点是不必复制属性,也不必在scopedestroy函数中进行清理。
请注意,您必须删除directive属性以防止循环执行
()
angular.module('directions').directive('wrappedWithDiv'[
函数(){
变量定义={
限制:“A”,
编译:函数(元素、属性){
元素。removeAttr(“用div包裹”);
元素。替换为(“”)+
元素[0]。outerHTML+“”)
}
}
返回定义;
}
]);
基于此:
此指令执行转置,但转置的内容使用父范围,因此所有绑定都像转置的内容在使用包装器的原始范围内一样工作。这当然包括ng模型、最小值/最大值和其他验证指令/属性。应该适用于任何内容。我没有使用ng TRANCLUDE指令,因为我正在手动克隆元素并为它们提供父(控制器)作用域。“我的幽魂”
app.directive("checkboxWrapper", [function() {
return {
restrict: "A",
link: function(scope, element, attrs, ctrl, transclude) {
var wrapper = angular.element('<div class="wrapper">This input is wrappered</div>');
element.after(wrapper);
wrapper.prepend(element);
scope.$on("$destroy", function() {
wrapper.after(element);
wrapper.remove();
});
}
};
}
]);
angular.module('directives').directive('wrappedWithDiv', [
function() {
var definition = {
restrict: 'A',
compile: function(element, attrs) {
element.removeAttr("wrapped-with-div");
element.replaceWith("<div style='border:2px solid blue'>" +
element[0].outerHTML + "</div>")
}
}
return definition;
}
]);
controlsModule.directive('myWrapper', function () {
return {
restrict: 'E',
transclude: true,
scope: {
label: '@',
labelClass: '@',
hint: '@'
},
link: link,
template:
'<div class="form-group" title="{{hint}}"> \
<label class="{{labelClass}} control-label">{{label}}</label> \
<my-transclude></my-transclude> \
</div>'
};
function link(scope, iElement, iAttrs, ctrl, transclude) {
transclude(scope.$parent,
function (clone, scope) {
iElement.find("my-transclude").replaceWith(clone);
scope.$on("$destroy", function () {
clone.remove();
});
});
}
});