Tengo una propiedad en un componente de nivel superior que utiliza datos de una fuente HTTP como esta (esto está en un archivo llamado 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"); } ); } } Ahora, tengo otro Componente que es un elemento secundario directo del Componente de nivel superior y dentro de él me gustaría acceder a la propiedad principal ' userStatus ', aquí está el elemento secundario:
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 } } Ahora, en Angular 1.x, esto sería fácil, ya que podría hacer referencia a $parent en mi controlador secundario o ( ¡¡ALERTA ANTI PATRÓN !!! ) Podría ser tan tonto como para poner estos datos en mi $rootScope .
¿Cuál sería la mejor manera de acceder al padre en Angular 2?
Hay diferentes maneras:
servicio mundial
servicio compartido por el padre e inyectado al niño
providers o viewProviders en el padre en lugar de boostrap(...) y solo disponible para los hijos del padre.padre inyectado al niño y accedido directamente por el niño
export class Profile implements OnInit { constructor(@Host() parent: App) { parent.userStatus ... } export class Profile implements OnInit { @Input() userStatus:UserStatus; ... } <profile [userStatus]="userStatus">Tuve el mismo problema pero lo resolví de otra manera. No sé si es una buena manera de hacerlo, pero funciona muy bien para lo que necesito.
Usé @Inject en el constructor del componente secundario, así:
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; } }Esto funcionó para mí, solo necesita declarar el método o la propiedad que desea llamar como público.
En mi caso, AppComponent maneja el enrutamiento y estoy usando insignias en los elementos del menú para alertar al usuario que hay nuevos mensajes no leídos disponibles. Entonces, cada vez que un usuario lee un mensaje, quiero que ese contador se actualice, así que llamo al método de actualización para que el número en el menú de navegación se actualice con el nuevo valor. Probablemente esta no sea la mejor manera, pero me gusta por su simplicidad.
Hice un componente genérico donde necesito una referencia al padre que lo usa. Esto es lo que se me ocurrió:
En mi componente hice un @Input:
@Input() parent: any;Luego, en el padre usando este componente:
<app-super-component [parent]="this"> </app-super-component>En el súper componente puedo usar cualquier cosa pública que venga del padre:
Atributos:
parent.anyAttributeFunciones:
parent[myFunction](anyParameter)y, por supuesto, no se podrá acceder a las cosas privadas.