Angular 角度结构指令和渲染器2

Angular 角度结构指令和渲染器2,angular,typescript,angular2-directives,angular-renderer2,Angular,Typescript,Angular2 Directives,Angular Renderer2,我有一个自定义的checkbox指令,它在传统的label/span样式中添加样式以及一些其他功能。它将包装器注入自身周围,并沿着跨度注入。我刚刚意识到,当放入一个结构化指令时,它无法操作DOM。大多数设置都是在构造函数中完成的,但我认为可能这需要更多的角度生命周期意识,以便更好地与结构父级配合 问题DOM示例: <ng-container *ngIf="test"> <!-- <div class="row align-middle"> -->

我有一个自定义的checkbox指令,它在传统的label/span样式中添加样式以及一些其他功能。它将包装器注入自身周围,并沿着跨度注入。我刚刚意识到,当放入一个结构化指令时,它无法操作DOM。大多数设置都是在构造函数中完成的,但我认为可能这需要更多的角度生命周期意识,以便更好地与结构父级配合

问题DOM示例:

  <ng-container *ngIf="test">
    <!-- <div class="row align-middle"> -->
      <input type="text" alloy placeholder="you should see a checkbox">
      <input type="checkbox" alloy alloyLabel="default">
    <!-- </div> -->
  </ng-container>
编辑:添加了结果DOM 没有实际的错误。在有缺陷的情况下(ng container的直接父元素),我以初始元素结束,但没有注入:

使用包装器
div
我得到了预期的注入(\u ngcontent*已删除):


违约

这可能是因为当一个元素位于ng容器中的顶层时,它的构造要早于ngIf变为true时,即添加到DOM之前

要解决此问题,您需要将修改DOM的逻辑从构造函数移动到ngOnInit,例如:

constructor(
    protected el: ElementRef,
    protected renderer: Renderer2,
    protected focusMonitor: FocusMonitor,
    @Host() @Optional() protected identityDirective: AlloyIdentityDirective) {
    super();
}

ngOnInit() {
    // If we don't have a label wrapper, create one
    this.labelElement = this.renderer.parentNode(el.nativeElement);
    if (!(this.labelElement instanceof HTMLLabelElement)) {
        const label = this.renderer.createElement('label');

        // Inject wrapper then move native element (input) within it.
        this.renderer.insertBefore(this.labelElement, label, this.el.nativeElement);
        this.renderer.removeChild(this.labelElement, this.el.nativeElement);
        this.renderer.appendChild(label, this.el.nativeElement);
        this.labelElement = label;
    }

    // We must add the span because that's what actually gets the check styling
    this.styledElement = this.renderer.createElement('span');
    this.renderer.appendChild(this.labelElement, this.styledElement);
}

对于修改DOM,无论如何,这几乎肯定是一种更好的做法,因为在构造函数执行时,您永远无法确定它是否正确地存在于DOM中。

有几个问题-它是否出错,或者只是无法注入任何东西?即使指令没有输出,输入元素是否仍然存在?好问题,我的疏忽。我会补充问题的。谢谢。。。标签的“外部”是什么?我感觉这一行:
this.labelement=this.renderer.parentNode(el.nativeElement)可能会以某种方式参与其中。。。也许ng容器在某种程度上弄乱了或干扰了父节点。是的,这是我首先想到的,但我怀疑它只是没有通过if语句,这意味着标签已经生成(事实上我认为if过于谨慎)。然而,我的测试示例中的外部节点是:
我猜构造函数在生命周期中的某个早期点(ngIf变为true时除外)为容器的直接子级执行。。。也许将init逻辑移动到ngOnInit会有所帮助?我不相信这是一个答案,但试一试。。。
<label class="alloy-check-wrapper">
  <input alloy="" alloylabel="default" type="checkbox" class="alloy-check">
  <span></span>
  <span class="alloyLabel">default</span>
</label>
constructor(
    protected el: ElementRef,
    protected renderer: Renderer2,
    protected focusMonitor: FocusMonitor,
    @Host() @Optional() protected identityDirective: AlloyIdentityDirective) {
    super();
}

ngOnInit() {
    // If we don't have a label wrapper, create one
    this.labelElement = this.renderer.parentNode(el.nativeElement);
    if (!(this.labelElement instanceof HTMLLabelElement)) {
        const label = this.renderer.createElement('label');

        // Inject wrapper then move native element (input) within it.
        this.renderer.insertBefore(this.labelElement, label, this.el.nativeElement);
        this.renderer.removeChild(this.labelElement, this.el.nativeElement);
        this.renderer.appendChild(label, this.el.nativeElement);
        this.labelElement = label;
    }

    // We must add the span because that's what actually gets the check styling
    this.styledElement = this.renderer.createElement('span');
    this.renderer.appendChild(this.labelElement, this.styledElement);
}