How to emit an event from parent to child?
Using RxJs, you can declare a Subject
in your parent component and pass it as Observable
to child component, child component just need to subscribe to this Observable
.
Parent-Component
eventsSubject: Subject<void> = new Subject<void>();
emitEventToChild() {
this.eventsSubject.next();
}
Parent-HTML
<child [events]="eventsSubject.asObservable()"> </child>
Child-Component
private eventsSubscription: Subscription;
@Input() events: Observable<void>;
ngOnInit(){
this.eventsSubscription = this.events.subscribe(() => doSomething());
}
ngOnDestroy() {
this.eventsSubscription.unsubscribe();
}
As far as I know, there are 2 standard ways you can do that.
1. @Input
Whenever the data in the parent changes, the child gets notified about this in the ngOnChanges method. The child can act on it. This is the standard way of interacting with a child.
Parent-Component
public inputToChild: Object;
Parent-HTML
<child [data]="inputToChild"> </child>
Child-Component: @Input() data;
ngOnChanges(changes: { [property: string]: SimpleChange }){
// Extract changes to the input property by its name
let change: SimpleChange = changes['data'];
// Whenever the data in the parent changes, this method gets triggered. You
// can act on the changes here. You will have both the previous value and the
// current value here.
}
- Shared service concept
Creating a service and using an observable in the shared service. The child subscribes to it and whenever there is a change, the child will be notified. This is also a popular method. When you want to send something other than the data you pass as the input, this can be used.
SharedService
subject: Subject<Object>;
Parent-Component
constructor(sharedService: SharedService)
this.sharedService.subject.next(data);
Child-Component
constructor(sharedService: SharedService)
this.sharedService.subject.subscribe((data)=>{
// Whenever the parent emits using the next method, you can receive the data
in here and act on it.})
In a parent component you can use @ViewChild() to access child component's method/variable.
@Component({
selector: 'app-number-parent',
templateUrl: './number-parent.component.html'
})
export class NumberParentComponent {
@ViewChild(NumberComponent)
private numberComponent: NumberComponent;
increase() {
this.numberComponent.increaseByOne();
}
decrease() {
this.numberComponent.decreaseByOne();
}
}
Update:
Angular 8 onwards -
@ViewChild(NumberComponent, { static: false })
Use the @Input() decorator in your child component to allow the parent to bind to this input.
In the child component you declare it as is :
@Input() myInputName: myType
To bind a property from parent to a child you must add in you template the binding brackets and the name of your input between them.
Example :
<my-child-component [myChildInputName]="myParentVar"></my-child-component>
But beware, objects are passed as a reference, so if the object is updated in the child the parent's var will be too updated. This might lead to some unwanted behaviour sometime. With primary types the value is copied.
To go further read this :
Docs : https://angular.io/docs/ts/latest/cookbook/component-communication.html