I'm currently reading about two way data binding in Angular 2 and reading this article.
https://blog.thoughtram.io/angular/2016/10/13/two-way-data-binding-in-angular-2.html
In this article, there is a child component with an @Input and @Output which allows a value inside the component to be bonded to a variable on its parent.
export class CustomCounterComponent {
counterValue = 0;
@Output() counterChange = new EventEmitter();
@Input()
get counter() {
return this.counterValue;
}
set counter(val) {
this.counterValue = val;
this.counterChange.emit(this.counterValue);
}
decrement() {
this.counter--;
}
increment() {
this.counter++;
}
}
parent HTML
<custom-counter [(counter)]="counterValue"></custom-counter>
<p><code>counterValue = {{counterValue}}</code></p>
So for me, I understand why the @Input is needed - however I don't understand how the @Output counterChange works because it's not even being subscribed by anything on the parent. However, it is necessary to have it there and also have it called counterChange in order to work.
The author of the article says
The next thing we need to do, is to introduce an @Output() event with the same name, plus the Change suffix. We want to emit that event, whenever the value of the counter property changes. Let’s add an @Output() property and emit the latest value in the setter interceptor:
Why do we need to have the same name plus change suffix? Is this some sort of Angular convention that I'm unaware of? I'm just trying to figure out which fundamental concept I've missed so I can understand how this is working.
I have a plunker of the code here if it'll help.
https://plnkr.co/edit/BubXFDQ59ipxEdnEHWiG?p=preview
The @Output() 's type. Tells Angular to create a new event emitter and that the data it emits is of type string. For more information on EventEmitter , see the EventEmitter API documentation. The addNewItem() function uses the @Output() , newItemEvent , to raise an event with the value the user types into the <input> .
@Input() and @Output() allow Angular to share data between the parent context and child directives or components. An @Input() property is writable while an @Output() property is observable.
EventEmitterlink. Use in components with the @Output directive to emit custom events synchronously or asynchronously, and register handlers for those events by subscribing to an instance.
We use EventEmitter to notify data changes from child component to parent component.
The @Output() decorator enables the counterChange
EventEmitter to be used in the Angular event syntax - (event name)="function()"
.
What stumbles you in this case is the ability of Angular to desugar the [(counter)]
syntax (called 'banana in a box') to [counter]="..." (counterChange)="..."
. In other words, Angular will append *Change
suffix to the property binding value when sees [(property name)] syntax.
I hope this answers the first question.
As to Why do we need to have the same name plus change
suffix?, this is an Angular convention that helps utilizing the 'banana in a box' syntax.
Highly recommend this blog post that explains in details the Angular template syntax:
https://vsavkin.com/angular-2-template-syntax-5f2ee9f13c6a#4930
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With