访问父组件中的属性

我在一个顶级组件中有一个属性,它使用来自 HTTP 源的数据,如下所示(这在一个名为 app.ts的文件中) :

import {UserData} from './services/user-data/UserData';


Component({
selector: 'app', // <app></app>
providers: [...FORM_PROVIDERS],
directives: [...ROUTER_DIRECTIVES],
pipes: [],
template: require('./app.html')
})
@RouteConfig([
// stuff here
])


export class App {
// Please note that UserData is an Injectable Service I have written
userStatus: UserStatus;


constructor(private userData: UserData) {
this.userStatus = new UserStatus();
}


ngOnInit() {
this.userData.getUserStatus()
.subscribe(
(status) => {
this.userStatus = status; // I want to access this in my Child Components...
},
(err) => {console.log(err);},
() => {console.log("User status complete");            }
);
}
}

现在,我有另一个 Component,它是顶级 Component 的直接子组件,在它里面,我想访问父组件的属性‘ userStatus’,这是子组件:

Component({
selector: 'profile',
template: require('app/components/profile/profile.html'),
providers: [],
directives: [],
pipes: []
})


export class Profile implements OnInit {
constructor() {


}


ngOnInit() {
// I want to have access with the parent App Component, 'userStatus' propety here... I only want to read this property
}
}

现在在角1.x 这将是很容易的,因为我可以参考 $parent在我的子控制器或(反模式警报! ! !) ,我可以是如此愚蠢地把这个数据在我的 $rootScope

在角度2中,访问父节点的最佳方式是什么?

164279 次浏览

There are different way:

export class Profile implements OnInit {
constructor(@Host() parent: App) {
parent.userStatus ...
}
  • data-binding
export class Profile implements OnInit {
@Input() userStatus:UserStatus;
...
}


<profile [userStatus]="userStatus">

You could:

  • Define a userStatus parameter for the child component and provide the value when using this component from the parent:

    @Component({
    (...)
    })
    export class Profile implements OnInit {
    @Input()
    userStatus:UserStatus;
    
    
    (...)
    }
    

    and in the parent:

    <profile [userStatus]="userStatus"></profile>
    
  • Inject the parent into the child component:

    @Component({
    (...)
    })
    export class Profile implements OnInit {
    constructor(app:App) {
    this.userStatus = app.userStatus;
    }
    
    
    (...)
    }
    

    Be careful about cyclic dependencies between them.

I had the same problem but I solved it differently. I don't know if it's a good way of doing it, but it works great for what I need.

I used @Inject on the constructor of the child component, like this:

import { Component, OnInit, Inject } from '@angular/core';
import { ParentComponent } from '../views/parent/parent.component';


export class ChildComponent{
constructor(@Inject(ParentComponent) private parent: ParentComponent){


}


someMethod(){
this.parent.aPublicProperty = 2;
}
}

This worked for me, you only need to declare the method or property you want to call as public.

In my case, the AppComponent handles the routing, and I'm using badges in the menu items to alert the user that new unread messages are available. So everytime a user reads a message, I want that counter to refresh, so I call the refresh method so that the number at the menu nav gets updated with the new value. This is probably not the best way but I like it for its simplicity.

I made a generic component where I need a reference to the parent using it. Here's what I came up with:

In my component I made an @Input :

@Input()
parent: any;

Then In the parent using this component:

<app-super-component [parent]="this"> </app-super-component>

In the super component I can use any public thing coming from the parent:

Attributes:

parent.anyAttribute

Functions :

parent[myFunction](anyParameter)

and of course private stuff won't be accessible.

On Angular 6, I access parent properties by injecting the parent via constructor. Not the best solution but it works:

 constructor(@Optional() public parentComponentInjectionObject: ParentComponent){
// And access like this:
parentComponentInjectionObject.thePropertyYouWantToAccess;
}

Since the parent-child interaction is not an easy task to do. But by having a reference for the parent component in the child component it would be much easier to interact. In my method, you need to first pass a reference of the parent component by calling the function of the child component. Here is the for this method.

The Code For Child Component.

    import { Component, Input,ElementRef,Renderer2 } from '@angular/core';


import { ParentComponent } from './parent.component';


@Component({
selector: 'qb-child',
template: `<div class="child"><button (click)="parentClickFun()">Show text Of Parent Element</button><button (click)="childClickFun()">Show text Of Child Element</button><ng-content></ng-content></div>`,
styleUrls: ['./app.component.css']
})
export class ChildComponent  {
constructor(private el: ElementRef,private rend: Renderer2){


};


qbParent:ParentComponent;
getParent(parentEl):void{
this.qbParent=parentEl;
console.log(this.el.nativeElement.innerText);
}
@Input() name: string;
childClickFun():void{
console.log("Properties of Child Component is Accessed");
}


parentClickFun():void{
this.qbParent.callFun();
}
}

This is Code for parent Component

import { Component, Input , AfterViewInit,ContentChild,ElementRef,Renderer2} from '@angular/core';


import { ChildComponent } from './child.component';


@Component({
selector: 'qb-parent',
template: `<div class="parent"><ng-content></ng-content></div>`,
styleUrls: ['./app.component.css']
})
export class ParentComponent implements AfterViewInit {
constructor(private el: ElementRef,private rend: Renderer2){


};
@Input() name: string;
@ContentChild(ChildComponent,{read:ChildComponent,static:true}) qbChild:ChildComponent;


ngAfterViewInit():void{
this.qbChild.getParent(this);
}


callFun():void{
console.log("Properties of Parent Component is Accessed");
}


}

The Html Code

<qb-parent>
This is Parent
<qb-child>
This is Child
</qb-child>
</qb-parent>

Here we pass the parent component by calling a function of the child component. The link below is an example of this method. Click here!

Declare #contentChild on the child component, then on the parent declare @ContentChild('contentChild') childContent;

Then: this.childContent.whatever gives you full access to child.

You can find a reference to a parent component in several ways.

@Input() dialogInput: DialogComponent;


constructor(
@Host() private dialogHost: DialogComponent,
private dialogDirect: DialogComponent,
@Inject(DialogComponent) private dialogInjected: DialogComponent,
@Inject(forwardRef(() => DialogComponent)) private dialogForward: DialogComponent
private injector: Injector
)
      

ngAfterViewInit(){
const dialogInjector: DialogComponent = this.injector.get<DialogComponent>(DialogComponent);
}

If you want the component to be available also in content projection this doesn't work.. I think you need a service for this so you can use DI

You can also add static before property name Eg - static myVariable = 5 and import parent component in child component and then just access it using parentcomponent.myVariable; Static method will make that property available outside component.