简体   繁体   English

如何将指令模板的属性附加到AngularJS中父元素以外的其他元素?

[英]How to attach attributes of a directive template to other elements than the parent in AngularJS?

I'd like to implement a directive that converts <specialInput></specialInput> into something like 我想实现一个指令,将<specialInput></specialInput>转换为类似

<div id="myDiv">
    <label></label>
    <input></input>
</div>

However, all attributes that the user provides by putting them into the specialInput -tag like <specialInput id="test" class="test2" ... required></specialInput> are currently attached to the div element myDiv. 但是,用户通过将它们放入specialInput -tag中提供的所有属性(例如<specialInput id="test" class="test2" ... required></specialInput>当前都附加到div元素myDiv。 Rather than that, I would like to attach all attributes to the input -tag. 相反,我想将所有属性附加到input -tag。

Note: One solution would be manually attaching every possible attribute to the label tag by adding the variable (eg type="' + atts.type + '" ) to the template and then remove these attributes from the parent by using the linkfunction. 注意:一种解决方案是通过将变量(例如, type="' + atts.type + '" )添加到模板中,然后通过使用linkfunction从父级中删除这些属性,将每个可能的属性手动附加到label标签。 This is not what I want to achieve though. 这不是我想要实现的。 There are way too many possible attributes to consider this solution. 有太多可能的属性无法考虑此解决方案。

 // 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> 

You definitely don't want to create binding in scope for each attribute. 您绝对不想在每个属性的scope创建绑定。 Instead, the simplest and probably the most effective way to solve it, is to find an input element and then copy all attributes to it in compile function. 相反,解决该问题的最简单且可能是最有效的方法是找到一个输入元素,然后将所有属性复制到编译功能中。

Here is simplified version of your directive: 这是指令的简化版本:

.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;
        }
    };
});

Demo: http://plnkr.co/edit/sQRFzDN0nZJBinu8atOH?p=preview 演示: http //plnkr.co/edit/sQRFzDN0nZJBinu8atOH?p = preview

You have to use the compile feature of the directive to achieve what you want. 您必须使用指令的编译功能来实现所需的功能。

As long as you only want to move PLAIN ATTRIBUTES from parent element to inner, you are basically ok. 只要您只想将“普通属性”从父元素移动到内部,就可以了。 If you want to move DIRECTIVES attributes from parent to children, this is way more complicated. 如果要将DIRECTIVES属性从父级移动到子级,这将更加复杂。

The example the for first option ( only plain/html attribute, not moving stuff that will need to be compiled/linked on the child element ) would be : 第一个选项的示例(仅是plain / 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;
        }
    };
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 AngularJS自定义指令在继承父作用域时访问模板中的属性 - AngularJS Custom Directive Access attributes in Template while inheriting parent scope 如何在子指令模板中访问父指令属性 - How to access parent directive attributes inside the child directive template 如何创建一个新指令来编译Angularjs中的其他指令属性? - How to create a new directive that will compile other directive attributes in Angularjs? 使用模板在AngularJS指令中代理HTML属性 - Proxying HTML attributes in AngularJS directive with template 如何编写一个AngularJS指令来创建其他指令的DOM元素? - How to write an AngularJS directive that creates DOM elements that are other directives? 如何使用Jquery将click事件附加到AngularJS指令? - How to attach click event to AngularJS directive with Jquery? AngularJS指令-来自$ scope的模板和其他指令 - AngularJS directive - template from $scope with other directives 在AngularJS中,如何将指令绑定到除指令根元素之外的其他元素中? - In AngularJS, how do I bind a directive into an element other than the directive's root element? 通过父控制器AngularJS设置指令元素属性 - set directive element attributes through parent controller AngularJS 如何在保持对父范围的访问的同时从自定义指令访问元素属性? - How to access elements attributes from custom directive while keeping access to parent scope?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM