Does @Input give a two way binding?
The answer is "no". In your example, the value that you pass to the @Input
property is a reference to an object. If you had two-way binding, you could assign a new object to that property in the child component:
this.thing = { name: "world", nbm: 10 };
and the corresponding property in the parent component would be updated accordingly. That is not the case, as you can see in this stackblitz.
However, since the parent and child components have a reference to the same object, they can both modify one of its properties, and that change will be observed in the other component.
In order to implement two-way binding, you can add an @Output
property with the same name followed by Change
, and emit the event when the change occurs:
@Input() thing: any;@Output() thingChange = new EventEmitter();setNewObject(){ this.thing = { name: "world", nmb: 10 }; this.thingChange.emit(this.thing);}
The change will then be reflected to the parent component if the two-way binding syntax is used:
<child2 [(thing)]="thing"></child2>
See this stackblitz for a demo.
If you want to prevent the child component from modifying the original object, you should bind the object properties instead of the object itself:
@Input() thingName: string;@Input() thingNmb: number;
<child [thingName]="thing.name" [thingNmb]="thing.nmb"></child>
Yes, Angular Change Detection
flows from parent
to child
however what you are experiencing is not related to Object
reference
. Since the shared object in parent
and child
point to the same reference
, it will update in both the component.
Whenever you make any change through child component, shared object will be changed in the parent component as well and Angular will detect changes and trigger the UI update.
However that is not same case with primitive data type. What you have thought is true for primitive data type. In case primitive data type changes moves from Parent to child not vice versa.
Here is the demo for the same - https://stackblitz.com/edit/angular-1wusrc
Two way data binding is the combination of both event
binding and property
binding banana like syntax - Where [(ngModel)]
is the combination of [ngModel]
and (ngModelChange)
events
Here comes the magic with the word Change
when a model name followed by the Change
word angular will recognize that it will be two way data binding and makes it to work as like that
Coming to Child
component @Input()
is the kind off passing data to the child as property
binding whereas @Output()
is the kind off emitting data from the child to the parent as event
binding - So to achieve two way binding you need both - check the example below
getModelList: any[]; @Output() modelListChange: EventEmitter<any[]> = new EventEmitter<any[]>(); @Input() get modelList(): any[] { return this.getModelList; } set modelList(value) { this.getModelList = value; this.modelListChange.emit(this.getModelList); }
In the above code we have modelList
property and modelListChange
property with the combination of both the bindings so we can access the modelList
property as [(modelList)]="value"
and that is your two way binding property
Accessing from parent - <multi-dropdown [(modelList)]="value"></multi-dropdown>
now your parent property will be updated based on two way data binding - Make sure you spell the Change
correctly which is case sensitive too
Hope this will help you - Thanks Happy coding !!