javascript - ¿Cómo emitir un evento desde los nietos hasta el abuelo en Angular moderno?
Si tengo varios niveles de componentes Angular, ¿cómo puedo usar @Output para emitir un evento desde un hijo hasta el abuelo?
Abuelo/a:
<parent (handleClick)="grandmaHandleClick($event)">
<parent>
...
grandmaHandleClick(event) {
console.log('grandma knows you clicked')
}
Padre:
<child (handleClick)="handleClick($event)">
</child>
Niño :
<div (click)="onClick()">Click button
</div>
...
@Output() handleClick = new EventEmitter
onClick() {
this.handleClick.emit('clicked a button')
}
Estoy tratando de hacer que @Output pueda pasar propiedades a través de varios componentes, ¿cuál es la mejor manera de lograr esto y puedes proporcionar un ejemplo?
Respuesta #1
Podría haber 2 maneras:
- Usando
@output:
Abuelo/a
<parent (notifyGrandParent)="grandmaHandleClick($event)">
<parent>
...
grandmaHandleClick(event) {
console.log('grandma knows you clicked')
}
Padre:
<child (handleClick)="childEvent($event)">
</child>
@Output() notifyGrandParent= new EventEmitter();
childEvent(event) {
this.notifyGrandParent.emit('event')
}
Child está implementado correctamente en el código, por lo que está listo para usar.
- Usando
BehaviorSubjecta través deService: Con este nivel de anidamiento, en realidad puedes crear un servicio comoEventService, y luego crear unBehaviorSubjectal que el Abuelos puede suscribirse directamente. Además, para hacer que esteserviciosea más específico de un componente, puedes mantener este servicio en unmóduloque tendrá otros 3 componentes (Abuelo, Padre y Hijo)
export class EventService{
private childClickedEvent = new BehaviorSubject<string>('');
emitChildEvent(msg: string){
this.childClickedEvent.next(msg)
}
childEventListner(){
return this.childClickedEvent.asObservable();
}
}
y luego en components:
ComponenteHijo
export class ChildComponent{
constructor(private evtSvc: EventService){}
onClick(){
this.evtSvc.emitChildEvent('clicked a button')
}
}
Abuelo
export class GrandComponent{
constructor(private evtSvc: EventService){}
ngOnInit(){
this.evtSvc.childEventListner().subscribe(info =>{
console.log(info); // here you get the message from Child component
})
}
}
Tenga en cuenta que, con el evento @output, se crea un acoplamiento estrecho de componentes y, por lo tanto, se genera una fuerte dependencia (padre-hijo-nieto). Si el componente no es reutilizable y solo se crea para cumplir este propósito, entonces @output también tendrá sentido porque transmitirá el mensaje a cualquier nuevo desarrollador de que tienen una relación padre-hijo.
Crear un servicio para pasar datos también expone los datos a otros componentes que pueden inyectar service en constructor.
Entonces, la decisión debe tomarse en consecuencia.
Respuesta #2
Usa rxjs/subject, puede ser observador y observable al mismo tiempo.
Uso :
- Crear propiedad Subject en el servicio:
import { Subject } from 'rxjs';
export class AuthService {
loginAccures: Subject<boolean> = new Subject<boolean>();
}
- Cuando ocurre un evento en la página/componente hijo, usa:
logout() {
this.authService.loginAccures.next(false);
}
- Y suscríbete al tema en la página/componente principal:
constructor(private authService: AuthService) {
this.authService.loginAccures.subscribe((isLoggedIn: boolean) => {
this.isLoggedIn = isLoggedIn;
})
}
