Доступ к свойству в родительском компоненте
У меня есть свойство в компоненте верхнего уровня, который использует данные из источника 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"); }
);
}
}
Теперь у меня есть другой Компонент, который является прямым потомком Компонента верхнего уровня, и в нем я хотел бы получить доступ к родительскому свойству ' 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
}
}
Теперь в Angular 1.x это было бы легко, поскольку я мог ссылаться на $parent
в моем дочернем контроллере или (ANTI PATTERN ALERT !!!) Я мог бы быть настолько глуп, чтобы поместить эти данные в мой $rootScope
.
Каков наилучший способ доступа к родителю в Angular 2?
Ответы
Ответ 1
Существуют разные способы:
-
глобальная служба
-
служба, совместно используемая родителем и вводимая ребенку
- похож на глобальный сервис, но указан в
providers
или viewProviders
в родительском вместо boostrap(...)
и доступен только для детей родителя.
-
родитель, инъецированный в дочерний элемент и доступ непосредственно к нему
- недостаток: плотная муфта
export class Profile implements OnInit {
constructor(@Host() parent: App) {
parent.userStatus ...
}
export class Profile implements OnInit {
@Input() userStatus:UserStatus;
...
}
<profile [userStatus]="userStatus">
Ответ 2
У меня была такая же проблема, но я решил ее по-другому. Я не знаю, хорошо ли это, но он отлично работает для того, что мне нужно.
Я использовал @Inject в конструкторе дочернего компонента, например:
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;
}
}
Это сработало для меня, вам нужно только объявить метод или свойство, которое вы хотите вызвать как общедоступное.
В моем случае AppComponent обрабатывает маршрутизацию, и я использую значки в элементах меню, чтобы предупредить пользователя о наличии новых непрочитанных сообщений. Поэтому каждый раз, когда пользователь читает сообщение, я хочу, чтобы этот счетчик обновлялся, поэтому я вызываю метод обновления, чтобы номер в навигаторе меню обновлялся с новым значением. Это, вероятно, не самый лучший способ, но мне нравится его простота.
Ответ 3
Вы можете:
-
Определите параметр userStatus
для дочернего компонента и укажите значение при использовании этого компонента из родителя:
@Component({
(...)
})
export class Profile implements OnInit {
@Input()
userStatus:UserStatus;
(...)
}
и в родительском:
<profile [userStatus]="userStatus"></profile>
-
Вставьте родительский элемент в дочерний компонент:
@Component({
(...)
})
export class Profile implements OnInit {
constructor(app:App) {
this.userStatus = app.userStatus;
}
(...)
}
Будьте осторожны с циклическими зависимостями между ними.
Ответ 4
Я создал общий компонент, где мне нужна ссылка на родителя, использующего его. Вот что я придумал:
В моем компоненте я сделал @Input:
@Input()
parent: any;
Затем в родительском элементе:
<app-super-component [parent]="this"> </app-super-component>
В суперкомпонентном я могу использовать что-либо, компилирующееся из родителя:
Атрибуты:
parent.anyAttribute
Функции:
parent[myFunction](anyParameter)
Ответ 5
На Angular 6 я получаю доступ к родительским свойствам, вводя родительский объект через конструктор. Не лучшее решение, но оно работает:
constructor(@Optional() public parentComponentInjectionObject: ParentComponent){
// And access like this:
parentComponentInjectionObject.thePropertyYouWantToAccess;
}
Ответ 6
Поскольку взаимодействие между родителями и детьми не является легкой задачей. Но при наличии ссылки на родительский компонент в дочернем компоненте было бы намного легче взаимодействовать. В моем методе вы должны сначала передать ссылку на родительский компонент, вызвав функцию дочернего компонента. Вот для этого метода.
Код для дочернего компонента.
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();
}
}
Это код для родительского компонента
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");
}
}
Здесь мы передаем родительский компонент, вызывая функцию дочернего компонента. Ссылка ниже является примером этого метода. Нажмите здесь !