如何在AngularJS中将指令模板的属性附加到父元素之外的其他元素
How to attach attributes of a directive template to other elements than the parent in AngularJS?
我想实现一个转换<specialInput></specialInput>
变成类似的东西
<div id="myDiv">
<label></label>
<input></input>
</div>
但是,用户通过将它们放入specialInput
-标记(如<specialInput id="test" class="test2" ... required></specialInput>
)提供的所有属性当前都附加到div元素myDiv。我希望将所有属性附加到input
-标记
注意:一种解决方案是通过将变量(例如type="' + atts.type + '"
)添加到模板中,手动将每个可能的属性附加到标签标签,然后使用链接函数从父标签中删除这些属性。但这不是我想要实现的。有太多可能的属性需要考虑这个解决方案。
// special-input Angular
(function () {
'use strict';
function specialInputDirective($compile) {
function templateFunction(element, attrs) {
var template = [
'<div class="control-group">'+
'<label for="' + attrs.name + '" class="control-label">' + attrs.label + '</label>' +
' <div class="controls">' +
' <input id="' + attrs.id + '" type="' + attrs.type + '" ' +
' ng-model="' + attrs.name + '" ' +
(attrs.ngTrueValue ? 'ng-true-value="' + attrs.ngTrueValue + '" ' : '') +
(attrs.ngFalseValue ? 'ng-false-value="' + attrs.ngFalseValue + '"' : '') +
' " placeholder="' + attrs.placeholder + '"' + ' ' +
attrs.required + ' ' + attrs.disabled + ' ' + attrs.readonly +
' name="' + attrs.name + '"' +
' required>' +
' </div>' +
'</div>'
].join('');
return template;
}
return {
link: linkFunction,
restrict: 'E',
replace: true,
transclude: true,
template: templateFunction
};
//////////
function linkFunction(scope, inputElement, attrs, ctrl, transcludeFn) {
// Removes user defined attributes from 'control-group'.
// These are added to the <input> element instead (Defined in: Template)
// BUT: there are many, many more attributes than this! So this is not the solution I'm aiming for.
inputElement.removeAttr('id');
inputElement.removeAttr('type');
inputElement.removeAttr('label');
inputElement.removeAttr('placeholder');
inputElement.removeAttr('required');
inputElement.removeAttr('disabled');
inputElement.removeAttr('readonly');
inputElement.removeAttr('name');
}
}
//////////
function initModule(angular) {
...
}
}());
<form name="myForm" class="form-horizontal" style="max-width: 700px;">
<h4>Horizontal Label</h4>
<special-input name="myName" type="email" label="Email" placeholder="Email"></special-input>
<special-validation for="myForm.myName" message="required" type="error">This message box represents an error</special-validation>
<special-validation for="myForm.myName" message="minlength" type="warning">This message box represents a warning</special-validation>
<special-validation for="myForm.myName" message="maxlength">This message box represents an error</special-validation>
<special-validation for="myForm.myName" message="email">Invalid email address</special-validation>
<special-input type="text" label="Text" placeholder="Required input" name="myName2" ng-minlength="5" ng-maxlength="20" required></special-input>
<special-input type="password" label="Password" placeholder="Password"></special-input>
</form>
您肯定不想在scope
中为每个属性创建绑定。相反,解决它的最简单、可能也是最有效的方法是找到一个输入元素,然后在编译函数中将所有属性复制到它。
以下是您指令的简化版本:
.directive('specialInput', function() {
function linkFunction(scope, element, attrs) {
// Do something else, bind events, etc ...
}
return {
transclude: true,
template: function(element, attrs) {
return '' +
'<div class="control-group">' +
' <label for="' + attrs.name + '">' + attrs.label + '</label>' +
' <input>' +
'</div>';
},
compile: function(element, attrs) {
var input = element.find('input');
// Copy attrbutes
angular.forEach(attrs.$attr, function(val, key) {
input.attr(val, attrs[key]);
});
element.replaceWith(element.children()[0]);
return linkFunction;
}
};
});
演示:http://plnkr.co/edit/sQRFzDN0nZJBinu8atOH?p=preview
您必须使用指令的编译功能来实现您想要的功能。
只要你只想将PLAIN属性从父元素移动到内部元素,你基本上就可以了。如果你想将DIRECTIVES属性从父属性移动到子元素,这要复杂得多。
例如,for first选项(只有纯html属性,不移动需要在子元素上编译/链接的内容)是:
/**
* Input wrapper directive, used to copy all attributes to the underneath input element.
*
* To keep a property on the wrapper, prefix it with "wrapper-*"
* In example, "wrapper-class" will create the "class" property on the wrapper, where "class" will be copied to the input.
*/
module.directive("tlInputWrapper", function($compile) {
// TODO : keep ngShow, ngIf... and other logic directive on the wrapper.
return {
restrict : "A",
compile : function($el, $attrs) {
var input = $el.find("input"); // here, you find the child element you wanna move attributes to
$attrs.$set("tlInputWrapper", null);
var attributesToKeep = {};
_.each($attrs.$attr, function(domAttributeName, normalizedAttributeName) {
if(domAttributeName.indexOf("wrapper-") === 0) { // I allow keeping attributes on the wrapper. Ex : 'wrapper-class' will stay on the wrapper and be renamed 'class'
attributesToKeep[domAttributeName.substring(8)] = $attrs[normalizedAttributeName];
$attrs.$set(normalizedAttributeName, null);
} else {
input.attr(domAttributeName, $attrs[normalizedAttributeName]);
$attrs.$set(normalizedAttributeName, null);
}
});
_.each(attributesToKeep, function(attrValue, attrName) {
$attrs.$set(attrName, attrValue);
});
return angular.noop;
}
};
});
相关文章:
- 如何覆盖锚点元素's href目标,并在我点击转到目标javascript时删除其他错误
- 如何在不影响其他元素的情况下扩展DIV
- 单击其他元素时,我如何使用 jQuery 忽略更改事件
- 如何查明鼠标按下事件是否发生在滚动条上或元素中的其他任何位置
- 从其他元素上的单击事件访问image src属性
- 如何'剪切'DOM元素并将其显示在其他位置
- jQuery悬停动画只在其他类似元素中的一个元素上
- 基本D3.js:如何将具有其他属性的数据绑定到元素
- 单击其他元素或鼠标向上时隐藏输入框,但保留一次焦点
- 将一个元素放在具有相同z索引的其他元素前面
- 将href中的图像替换为其他元素中的图像
- JavaScript删除所有其他元素
- AngularJS:根据其他对象预先选择ng repeat中的select元素
- 为数组元素的属性赋值将设置所有其他类似元素的属性
- 如何使用其他自定义指令中的元素标记作为另一个自定义指令的模板
- stopPropagation是否还会阻止同一元素上的其他处理程序运行
- 如何在 *ngFor 列表中显示单击的元素,使用 Angular 2 隐藏其他元素
- 单击更改其他元素源
- 有没有办法将选择器返回到元素?是$(这个)还是其他方法
- 从异步调用返回数组,然后为数组的每个元素返回其他异步调用