将指令中的输入包装成角度

roe*_*mer 14 angularjs angularjs-directive angular-ui-bootstrap

我有想法将输入包装到自定义指令中,以保证整个网站的外观和行为一致.我还想包装bootstrap ui的datepicker和dropdown.此外,该指令应处理验证和显示工具提示.

HTML应该看起来像这样:

<my-input required max-length='5' model='text' placeholder='text' name='text'/>
Run Code Online (Sandbox Code Playgroud)

要么

<my-datepicker required model='start' placeholder='start' name='start'/>
Run Code Online (Sandbox Code Playgroud)

在指令中我想创建一个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>
Run Code Online (Sandbox Code Playgroud)

我尝试了各种方法来实现这一目标,但总是遇到一些权衡:

  1. 使用transclude和replace将输入插入到指令dom结构中(在这种情况下,指令将被限制为'A'而非'E',如上例所示).这里的问题是,没有简单的方法来访问transcluded元素,因为我想在datepicker的情况下添加自定义属性.我可以使用transclude函数,然后在链接函数中重新编译模板,但这对于此任务来说似乎有点复杂.这也会导致transcluded范围和datepicker的切换状态出现问题(一个在指令范围内,另一个在transcluded范围内).

  2. 仅使用替换.在这种情况下,所有属性都应用于最外层的div(即使我在编译函数中生成模板dom结构).如果我只使用输入作为模板,那么属性在输入上,但我需要在链接函数中生成模板然后重新编译它.据我所知,角度的相位模型,我想避免重新编译和更改链接函数中的模板dom(虽然我看到很多人这样做).

目前我正在使用第二种方法并在链接功能中生成模板,但我想知道是否有人有更好的想法!

Bra*_*ite 8

以下是我认为正确的方法.像OP一样,我希望能够使用属性指令来包装input.但我也希望它可以与之合作,ng-if而不会泄漏任何元素.正如@jantimon指出的那样,如果你不清理你的包装元素,它们会在ng-if之后停留,如果它会破坏原始元素.

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();
        });
      }
    };
  }
]);
Run Code Online (Sandbox Code Playgroud)

而且这里有一个plunker你可以玩.

重要提示:scopevs element$ destroy.你必须把你的清理放入scope.$on("$destroy")而不是element.on("$destroy")(这是我最初尝试的).如果你在后者(元素)中执行它,那么"ngIf end"注释标记将被泄露.这是由于Angular的ngIf在它做出错误逻辑时如何清理其结束注释标记.通过将指令的清理代码放在范围$ destroy中,您可以将DOM放回原来,就像它在输入之前一样,因此ng-if的清理代码很高兴.到调用element.on("$ destroy")时,在ng-if falsey流程中打开原始元素而不导致注释标记泄漏为时已晚.


Arm*_*min 2

为什么不执行这样的指令呢?

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('');
                }
            });            
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

小提琴: http: //jsfiddle.net/bZ6WL/

基本上,您采用原始输入字段(顺便说一下,这也是一个 angularjs 指令)并单独构建包装。在此示例中,我只是手动构建 DIV。$compile对于更复杂的东西,您还可以使用由 angularjs 获取 (d)的模板。

使用此类或 html 属性“wrapForm”的优点:您可以对多种表单输入类型使用相同的指令。