首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用@ViewChild与外部ng-模板(角11)

如何使用@ViewChild与外部ng-模板(角11)
EN

Stack Overflow用户
提问于 2021-02-20 04:59:45
回答 1查看 4.7K关注 0票数 5

问题

所以我有两个角度分量,一个父母和一个孩子。父组件将一个自定义模板传递给子组件,然后子组件使用ngTemplateOutlet使用自己的数据补充模板。

这在很大程度上运作良好。不幸的是,当试图从子模板访问这个父模板的DOM元素时,我遇到了一些问题。

如果我尝试使用<div #container></div>从默认子模板访问@ViewChild('container',{static: false}),它将获得元素,而不存在任何问题。当我使用app.component传入的自定义模板进行同样的操作时,会得到“无法读取未定义的属性'nativeElement‘”的错误。

为了访问模板的DOM,我还需要做什么呢?

这是一个斯塔克布利茨

App.Component (父)

代码语言:javascript
复制
import { Component } from "@angular/core";

@Component({
  selector: "my-app",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {}
代码语言:javascript
复制
<child [customTemplate]="parentTemplate"></child>

<ng-template #parentTemplate let-context="context">

    <div #container>HELLO FROM CONTAINER</div>
    <button (click)="context.toggleShow()">Toggle Display</button>
    <div *ngIf="context.canShow">Container contains the text: {{context.getContainerText()}}</div>
</ng-template>

child.component (儿童)

代码语言:javascript
复制
import {
  Component,
  ElementRef,
  Input,
  TemplateRef,
  ViewChild
} from "@angular/core";

@Component({
  selector: "child",
  templateUrl: "./child.component.html",
  styleUrls: ["./child.component.css"]
})
export class ChildComponent {
  @Input() public customTemplate!: TemplateRef<HTMLElement>;
  @ViewChild("container", { static: false })
  public readonly containerRef!: ElementRef;

  templateContext = { context: this };
  canShow: boolean = false;
  

  toggleShow() {
    this.canShow = !this.canShow;
  }
  getContainerText() {
    return this.containerRef.nativeElement.textContent;
  }
}
代码语言:javascript
复制
<ng-container *ngTemplateOutlet="customTemplate || defaultTemplate; context: templateContext">
</ng-container>

<ng-template #defaultTemplate>
    <div #container>GOODBYE FROM CONTAINER</div>
    <button (click)="toggleShow()">Toggle Display</button>
    <div *ngIf="canShow">Container contains the text: {{getContainerText()}}</div>
</ng-template>

我的问题

如何使用@ViewChild从外部模板访问这个div,该模板可以更新DOM中的任何更改?(注:删除*ngIf不是此项目的选项)

是什么引起的?有什么生命周期方法可以用来解决这个问题吗?

,我的直觉,,我猜,在DOM更新之前,会用它的新模板调用ViewChild,我需要为DOM更改设置一个侦听器。我试过了,但失败了,所以我真的很感激关于如何最好地继续下去的一些智慧。(预先谢谢:)

编辑:这个解决方案需要正确地显示<div #container></div>,不管您是传递自定义模板还是使用默认模板。

EN

回答 1

Stack Overflow用户

发布于 2021-02-20 12:01:32

ViewChild似乎没有选择呈现的模板--可能是因为它最初不是组件模板的一部分。这不是时间问题,也不是生命周期问题,只是不能作为ViewChild使用

一种可行的方法是将模板作为内容传递给子组件,并使用ContentChildren访问它。订阅ContentChildren QueryList for changes,它将在呈现DOM元素时进行更新。

然后可以访问nativeElement ( div)。如果您愿意,可以在这里将侦听器添加到DOM元素中,然后触发cd.detectChanges,但这有点不寻常。最好处理父元素中的DOM更改,并使用子元素上的常规@Input将所需的值向下传递给子元素。

代码语言:javascript
复制
@Component({
  selector: "my-app",
  template: `
    <child>
      <ng-template #parentTemplate let-context="context">
        <div #container>Parent Template</div>
      </ng-template>
    </child>
  `,
  styleUrls: ["./app.component.css"]
})
export class AppComponent {}
代码语言:javascript
复制
@Component({
  selector: "child",
  template: `
    <ng-container *ngTemplateOutlet="customTemplate"> </ng-container>
  `,
  styleUrls: ["./child.component.css"]
})
export class ChildComponent implements AfterContentInit {
  @ContentChild("parentTemplate")
  customTemplate: TemplateRef<any>;

  @ContentChildren("container")
  containerList: QueryList<HTMLElement>;

  ngAfterContentInit() {
    this.containerList.changes.subscribe(list => {
      console.log(list.first.nativeElement.innerText);
      // prints 'Parent Template'
    });
  }
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66288186

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档