The behavior you're describing happens when the input isn't a primitive type (number/string/boolean). If it's a complex object (different from null
) and you change any property of the object, that change will reflect on the parent's object, because it's the same: you're dealing with references, not with values.
You must do a deep clone of the input if you want to avoid this situation, like this:
private _data: any;
@Input() set data(d: any) {
// If you want to improve performance, use this library to do a deep clone:
// https://github.com/planttheidea/fast-copy
// otherwise, you can go with JSON.parse(JSON.sringify(...))
this._data = d ? JSON.parse(JSON.sringify(d)) : null;
}
get data(): any {return this._data;}
Complementary info
Now, as info: to really use the 2-way data binding if you'd like to:
@Input() data:any = {}
// mandatory: the same name of the @Input, suffixed with "Change"
@Ouput() dataChange = new EventEmitter<any>();
Then you can use, in the parent, the "banana-in-the-box" notation:
<app-config-form [(data)]="param"></app-config> //param is ngModel
But the update is not automatically fired. Every time you change it in the child, you must call this.dataChange.emit(value)
.
For example (in the child):
buttonClickHandler() {
this.data = 2;
this.dataChange.emit(2);
}