如何在Angular 9中从子组件访问父组件

4

问题

  • 无法使用 viewContainerRef 进行父子通信。

这段代码在 Angular 8.2 中是可用的。

 this.viewContainerRef[ '_data' ].componentView.component.viewContainerRef[ '_view' ].component;

错误

ERROR TypeError: 无法读取未定义的 'componentView' 属性

公共 API https://angular.cn/api/core/ViewContainerRef

    this.viewContainerRef.get(0) still i got null

我需要从子组件访问父组件。

Angular版本

Package                      Version
------------------------------------------------------
@angular-devkit/architect    0.900.7
@angular-devkit/core         9.0.7
@angular-devkit/schematics   9.0.7
@schematics/angular          9.0.7
@schematics/update           0.900.7
rxjs                         6.5.3

无法在stackblitz中重现问题

https://stackblitz.com/edit/angular-testangular9-communicating-x

问题

ViewContainerRef在Angular 9中无法工作

可行的ViewContainerRef

enter image description here

在Angular 9中不可用的ViewConatinerRef enter image description here

欢迎任何建议。


1
主要问题是……为什么你不能在Stackblitz上复制它呢?也许在您的项目中还有其他您没有在Stackblitz上执行的操作?顺便说一下,为了在Stackblitz上运行它,您应该在 polyfills.ts 文件中注释掉 core-js 的行(这里是修复版本)。 - julianobrasil
谢谢,但我需要通过ViewContainerRef方式获取父组件,因为在Angular 8.2中它是有效的。代码在Angular 9中是相同的。 - afeef
请查看更新的viewconatineRef快照。 - afeef
1个回答

17

为了避免你已经遇到的问题,你绝对不应该访问第三方库的私有成员。幸运的是,如果我理解你想要做什么的话,有一些解决方案可以避免访问这些私有成员。我将展示3种解决方案,其中2种在本答案末尾引用的stackblitz上实现。

假设你有这样的情况:一个父组件具有一个propertyA,你想以某种原因直接在子组件中访问它。

父组件:

@Component({
  template: `
    <child></child>
  `
})
export class ParentComponent { propertyA: string; }

情况A:在子元素中直接注入父元素

@Component({selector: 'child', ...})
export class ChildComp {
  constructor(private _parent: ParentComponent) { this._parent.propertyA = 'some value'; }
}

场景B:通过子级的 ViewContainerRef 获取父级

@Component({selector: 'child', ...})
export class ChildComp {
  constructor(private viewContainerRef: ViewContainerRef) {
    const _injector = this.viewContainerRef.parentInjector;
    const _parent: ParentComponent = _injector.get<ParentComponent>(ParentComponent);  
    this._parent.propertyA = 'some value';
  }
}

这是重要的部分:Angular注入器的存在恰好可以做到您想要的,因此,与其试图自行引用组件,正确的做法是找出如何查找注入器来为您执行搜索。请记住,注入器按层次结构分布,如果一个注入器无法解析符号,则会要求其父注入器递归地尝试解析,直到到达根注入器。这将带我们走向第三种方法,直接获取组件的注入器:

Case C:通过子级注入器直接注入获取父级

@Component({selector: 'child', ...})
export class ChildComp {
  constructor(private _injector: Injector) { 
    const _parent: ParentComponent = this._injector.get<ParentComponent>(ParentComponent);  
    this._parent.propertyA = 'some value';
  }
}

情况B和情况C适用的原因是,您的组件在父子关系树的组件中分布,并且在某些时候它们将有一个共同的注入器,在声明/导入它们的模块上。

我已经修改了您的stackblitz,以展示这两种解决方案(A用于a-component,B用于b-component)。


非常感谢,我会看一下。 - afeef
4
请注意,从Angular 7开始,viewContainerRef.parentInjector已被弃用,没有替代方法。 - PeterS
2
有没有一种类似的方法可以在不知道其类型的情况下访问指令中的宿主组件? - Tarun Chopra
也许你可以通过使用引用变量来传递它:<host-c #comp [your-directive]="comp"></host-c> - julianobrasil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接