I have big object in my component, the properties in the object are bound to various components and inputs in the template:
constructor() {
this.data = {
identifier: null,
isRequired: true,
title: 'Untitled',
type: this.fileTypes[0].name,
description: '',
//more code here
}
<app-text-input [(model)]="data.title" label="Title" type="text" variant="white">
Since, all properties in data
are bound with various input elements, the values in the object are kept updated. This component is child of another component.
The parent needs to have access to the data
object when some event occurs (button click for example) on the parent. How do I achieve this? I know there are @Ouptuts
but the event is happening on the parent not on child. Also, I'm not using any FormControl classes for now, do I need to implement that to achieve this?
CodePudding user response:
Edit : Here is the way via event emitter, you need to subscribe to it in child component when the data is changed or emitted, Updated values will be displayed in child or any other component.
shared service
SharedService
subject: Subject<Object>;
Parent-Component
constructor(DataService: DataService)
this.DataService.event.next(data);
Child-Component
constructor(DataService: DataService)
this.DataService.event.subscribe((data)=>{
//emitted event with updated data
});
Whenever the parent emits using the next method, you can receive the data in child or other component and act on it.
CodePudding user response:
There are a couple ways to do this.
1. Use a BehaviorSubject
.
This would be best when using Reactive Forms instead of ngModel
:
Child Component:
@Input()
data: BehaviorSubject<T>;
form = new FormGroup({
title: new FormControl()
});
ngOnInit() {
this.form.valueChanges.subscribe(formData => {
this.data.next({
...this.data.value,
...formData
});
});
}
<div [formGroup]="form">
<input [formControlName]="title">
</div>
Parent Component:
<child [data]="data"></child>
data: BehaviorSubject<T>;
buttonClicked() {
// use this.data.value
}
2. Use two-way binding.
This still uses ngModel
, but will require you to customize the two-way bindings you are using on form elements to trigger the update:
Child Component:
@Input()
data: T;
@Output()
dataChange: EventEmitter<T>;
<input [model]="data.title" (modelChange)="data.title = $event; dataChange.next(data)">
Parent Component:
<child [(data)]="data"></child>
data: T;
buttonClicked() {
// use this.data
}
You could also mix & match these, e.g. use two-way data binding on ngModel as in 2., but pass a BehaviorSubject
from parent to child as in 1.