1
votes

Problem

  • cannot user viewContainerRef fro parent child communication.

Code was working in Angular 8.2

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

Error

ERROR TypeError: Cannot read property 'componentView' of undefined

Public Api https://angular.io/api/core/ViewContainerRef

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

I need to access parent component from child component.

Ng Version

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

Cannot replicate the issue in stackblitz

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

Problem

ViewContainerRef is not working in Angular 9

Working ViewContainerRef

enter image description here

Not working ViewConatinerRef in Angular 9 enter image description here

Any suggestion is most welcome.

1
The main question is... why can't you replicate it on stackblitz? Maybe there's something else in your project you didn't do on stackblitz? BTW, in order to run it on stackblitz, you should comment the core-js lines in polyfills.ts (here it is a fixed version). - julianobrasil
Thanks but i need to get parent component by viewconatinerRef way as it was working in Angular 8.2 code is same in Angular 9 - afeef
Please see updated snapshot of viewconatineRef - afeef

1 Answers

3
votes

You shouldn't (definitely) be accessing private members of a 3rd party library exactly to avoid the troubles you've got into. Fortunately, if I got right what you wanna do, there is something you can do to avoid accessing these private members. I'll show 3 solutions, 2 of them implemented on the stackblitz referenced at the end of this answer.

Let's suppose you have this scenario: a parent component that has a propertyA that you want to access directly in a child component for some reason.

Parent Component:

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

Case A: Injecting the parent directly in the child

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

Case B: Getting the parent through the child's 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';
  }
}

This is the important part: angular injectors exist exactly to do what you want, so instead of trying to get a reference to the component by yourself, the right thing to do is find out how to find an injector to do the search for you. Remember that the injectors are distributed in a hierarchy in such a way that if an injector cannot resolve a Symbol, it asks his parent injector to try to resolve it recursively until getting to the root injector. This lead us to a 3rd approach, getting the component's injector directly:

Case C: Getting the parent through the child's injector, injected directly

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

Cases B and C work because your components are distributed in a tree of components in a parent-nth-child relation and, at some point they'll have a common injector, at the module where they are declared/imported.

I've modified your stackblitz to show both of this solution (case A used on a-component, a the case B used on b-component),