如何解决如何将 @ViewChild 与外部 ng-template (Angular 11)
问题
所以我有两个 Angular 组件,一个父组件和一个子组件。父组件将自定义模板传递给子组件,然后子组件使用 ngTemplateOutlet 将模板与自己的数据混合。
这在大多数情况下效果很好。不幸的是,我在尝试从子模板访问该父模板的 DOM 元素时遇到了问题。
如果我尝试使用 <div #container></div>
从默认子模板访问 @ViewChild('container',{static: false})
,它会毫无问题地获取元素。当我使用 app.component 传入的自定义模板执行相同操作时,出现错误“无法读取未定义的属性 'nativeElement'”。
我还需要做什么才能访问模板的 DOM?
App.Component(父级)
import { Component } from "@angular/core";
@Component({
selector: "my-app",templateUrl: "./app.component.html",styleUrls: ["./app.component.css"]
})
export class AppComponent {}
<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(子)
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;
}
}
<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 不是这个项目的一个选项)
我的预感 我猜测 ViewChild 在使用其新模板更新 DOM 之前被调用,我需要为 DOM 更改设置一个侦听器。我试过这个但失败了,所以我真的很感激一些关于如何最好地进行的智慧。提前致谢:)
编辑:
无论您是传入自定义模板还是使用默认模板,此解决方案都需要正确显示 <div #container></div>
。
解决方法
try:
msg = await channel.fetch_message(msg_id)
embed = msg.embeds[0]
submitter = embed.description[embed.description.find('/n'):] # get submitter name
suggestion = embed.fields[0].value
# other stuff
except:
pass
# possible exceptions message not found,list index out of range(if wrong msg id with no embeds passed as arg)
似乎没有选择呈现的模板 - 可能是因为它最初不是组件模板的一部分。这不是时间或生命周期问题,只是永远无法作为 ViewChild
一种有效的方法是将模板作为内容传递给子组件,并使用 ViewChild
访问它。您为 ContentChildren
订阅了 ContentChildren
QueryList
,它会在 DOM 元素呈现时更新
然后您可以访问 changes
(nativeElement
)。如果您愿意,可以在此处向 DOM 元素添加侦听器,然后触发 div
,但这有点不寻常。处理父元素中的 DOM 更改可能会更好,并在子元素上使用常规 cd.detectChanges
将所需的值传递给子元素
@Input
@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 {}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。