javascript - 通过 @ViewChild 在视图中调用组件上的方法到 QueryList
问题描述
我想做一个可重用的组件,设置多个子组件并一次渲染一个组件,我在父组件处使用@ContenChildren 获得了一组视图,如下所示:
@ContentChildren(ChildComponent) children: QueryList<ChildComponent>;
//getCurrentChild function
getCurrentChild(){
//index is a position of child
return this.children.toArray()[this.index];
}
并渲染父模板:
<ng-container *ngTemplateOutlet="getCurrentChild().content"></ng-container>
使用@ViewChild 在子组件中呈现内容:
@ViewChild('currentChild') child;
模板如下所示:
<ng-template #currentChild>
<ng-content>
</ng-content>
</ng-template>
当我想实现这个结构时,我会做这样的事情:
<parent>
<child>
<specific-one></specific-one>
</child>
<child>
<specific-two></specific-two>
</child>
</parent>
现在我在父组件中有一个方法,该方法在单击按钮上触发,并且需要调用特定组件中的方法(具体一个或具体两个取决于 currentChild):
export class SpecificOneComponent implements OnInit{
action(){
//this action will be called when parent is clicked
}
}
我试过通过孩子调用方法reference
,但动作没有退出。也传递了一个上下文,也没有传递。看起来我在父模板中设置内容的方式不正确。
任何帮助将不胜感激。
解决方案
ng-template
每个子组件都有自己的内容,因此这意味着只获取对ng-content
.
此外,由于您希望在父级发生特定事件时调用特定组件的方法,因此我们将使用服务以便能够通知特定组件。
具体的.service.ts
private _shouldCallAction$ = new Subject();
shouldCallAction$ = this._shouldCallAction$.asObservable();
constructor() { }
triggerAction (uniqueCompId) {
this._shouldCallAction$.next(uniqueCompId);
}
具体-{一个|两个|...n}.component.ts
这适用于依赖于父组件中发生的某些事件的每个组件。
private shouldCallActionSubscription: Subscription;
uniqueId: number | string;
constructor(private specificService: SpecificService) {
this.uniqueId = randomId();
}
ngOnInit() {
this.shouldCallActionSubscription = this.specificService.shouldCallAction$
.pipe(
filter(id => id === this.uniqueId)
)
.subscribe(() => {
console.log('calling action for specific-one')
});
}
ngOnDestroy () {
this.shouldCallActionSubscription.unsubscribe();
}
child.component.html
<ng-container *ngIf="instanceIdx === crtIdx">
<h3>trigger action of current specific component</h3>
<button (click)="triggerAction()">trigger</button>
</ng-container>
<ng-template #currentChild>
<ng-content></ng-content>
</ng-template>
child.component.ts
在这里,您还需要获取对 的引用specificComponent
才能获得其唯一的 id。
// Before class
let instances = 0;
@ViewChild('currentChild', { static: true }) tpl: TemplateRef<any>;
@ContentChild('specific', { static: true }) specificComp;
get uniqueSpecificCompId () {
return this.specificComp.uniqueId;
}
constructor (private specificService: SpecificService) {
this.instanceIdx = instances++;
}
triggerAction () {
this.specificService.triggerAction(this.uniqueSpecificCompId);
}
父组件.ts
@ViewChildren(ChildOneComponent) children: QueryList<ChildOneComponent>;
@ViewChild('container', { static: true, read: ViewContainerRef }) container: ViewContainerRef;
crtIdx = 0;
ngAfterViewInit () {
this.setNewView();
}
setNewView () {
this.container.clear();
this.container.createEmbeddedView(this.children.toArray()[this.crtIdx].tpl);
}
updateIndex (idx) {
this.crtIdx = idx;
this.setNewView();
}
父组件.html
<app-child [crtIdx]="crtIdx">
<!-- ... -->
<app-specific-two #specific></app-specific-two>
</app-child>
<app-child [crtIdx]="crtIdx">
<!-- ... -->
<app-specific-one #specific></app-specific-one>
</app-child>
<ng-container #container></ng-container>
<h3>Select a child</h3>
<button
*ngFor="let _ of [].constructor(n); let idx = index;"
(click)="updateIndex(idx)"
>
Select {{ idx + 1 }}
</button>
这是演示。
祝你好运!
推荐阅读
- javascript - 返回动态对象结构
- node.js - 不能随续集增加:'关系“用户”的列“0”不存在'
- android - WebView - 是否可以覆盖从表单提交中获取值的方法?
- laravel-5 - 通过移动设备共享时共享代理 IP 地址而不是代理名称
- html - 如何在悬停状态下影响兄弟元素?
- android - 使用 IntentService 在 Oreo 及更高版本上进行位置跟踪
- angular - 无法从角度连接 laravel 网络套接字
- codeigniter - 我为 foreach 提供的应用程序无效参数有问题
- php - 无法使用 php 在 chrome 中显示从外部 url 加载的 pdf 文件
- selenium - 如何为 Mat-Icons 使用 Click Button 关键字?