【问题标题】:Angular 2 surrounding an input tag with div via directiveAngular 2 通过指令用 div 包围输入标签
【发布时间】:2017-09-03 02:09:01
【问题描述】:

我正在尝试创建一个指令,它接受一个输入元素并用一个 div 包围它,例如,我的 html 将类似于:

<input type="text" class="form-control" inputWrapper />

以及期望的结果:

<div class="input-wrapper">
    <input type="text" class="from-control" />
</div>

指令:

@Directive({
    selector: '[inputWrapper]'
})
export class InputWrapperDirective {
    constructor(private viewContainerRef: ViewContainerRef, private elementRef: ElementRef) {
        // what goes here?
    }
}

【问题讨论】:

  • 我相信 angular2 指令更常用于向现有 DOM 元素添加行为,而不是通常用于更改 DOM。
  • 我很好奇为什么你不只是在你的 html 中的元素周围添加
    标签。
  • 我正在尝试使其尽可能可重用,本质上我想在输入标签后附加 html,但需要在父 div 中进行一些内联​​样式
  • 我可能会使用组件而不是指令。

标签: angular angular2-directives


【解决方案1】:

我会使用一个组件...

我会这样做:

@Component({
    selector: 'input-wrapper',
    template: '<div><ng-content></ng-content></div>'
})
export class InputWrapperComponent {}

在模板中,&lt;ng-content&gt; 标签意味着无论你的&lt;input-wrapper&gt; 标签被包裹在此处。

注意这个组件模板是&lt;div&gt;&lt;ng-content&gt;&lt;/ng-content&gt;&lt;/div&gt;。您可以将“div”更改为您想要的任何内容...

无论你想在哪里使用它,你都不会只是注释一个标签,你需要做这样的事情:

<input-wrapper>
    <!-- Anything you want wrapped goes here -->
</input-wrapper>

这是相当可重用的...更改您的模板,您将更改所有包装。

【讨论】:

    【解决方案2】:

    以下是使用指令的方法。代码使用了 Renderer2,我认为它是 Angular 4。可能使用 Renderer 可以实现相同的效果(现在标记为已弃用)

    我在ngAfterViewInit 方法中完成了所有工作。您可能会改用构造函数。

    import { Directive, Renderer2, ElementRef, AfterViewInit } from '@angular/core'
    
    @Directive({
        selector: '[inputWrapper]'
    })
    export class InputWrapperDirective implements AfterViewInit {
        constructor(private _renderer:Renderer2, private _el: ElementRef) {
    
        }
    
        ngAfterViewInit() {
            // Get parent of the original input element
            var parent = this._el.nativeElement.parentNode;
    
            // Create a div
            var divElement = this._renderer.createElement("div");
    
            // Add class "input-wrapper"
            this._renderer.addClass(divElement, "input-wrapper");
    
            // Add the div, just before the input
            this._renderer.insertBefore(parent, divElement, this._el.nativeElement);
    
            // Remove the input
            this._renderer.removeChild(parent, this._el.nativeElement);
    
            // Remove the directive attribute (not really necessary, but just to be clean)
            this._renderer.removeAttribute(this._el.nativeElement, "inputWrapper"); 
    
            // Re-add it inside the div
            this._renderer.appendChild(divElement, this._el.nativeElement);
    
        }
    
    }
    

    【讨论】:

    • 附带说明,我并不是说采用指令方法比使用组件更好或更差。我只是在回答您最初的问题,即如何使用指令来完成。
    • 如果我们像上面那样删除和添加新元素,ngmodel 绑定会起作用吗?
    • 其实appendChild移动了一个节点。所以,前面的 removeChild 可以省略。
    【解决方案3】:

    这是另一个版本,这个版本使用 Renderer,而不是 Renderer2。请注意,这里我在构造函数中进行工作,将其推迟到 AfterViewInit 不起作用。

    import { Directive, Renderer, ElementRef } from '@angular/core';
    
    @Directive({
        selector: '[inputWrapper]'
    })
    export class InputWrapperDirective {
        constructor(private _renderer:Renderer, private _el: ElementRef) {
            // Remove the inputWrapper attribute (not really necessary, but just to be clean)
            this._renderer.setElementAttribute(this._el.nativeElement, "inputWrapper", null);
    
            // Get parent of the original input element
            var parent = this._el.nativeElement.parentNode;
    
            // Create a div and add it to the parent
            // Note: it seems that Renderer creates the element in the right place,
            // no need to specify where.
            var divElement = this._renderer.createElement(parent, "div");
    
            // Add class "input-wrapper"
            this._renderer.setElementClass(divElement, "input-wrapper", true);
    
            // Move the input as a child of the div
            divElement.appendChild(this._el.nativeElement);
        }
    }
    

    【讨论】:

      猜你喜欢
      相关资源
      最近更新 更多
      热门标签