Reputation: 42957
I am starting with Angular and I have some doubts about how exactly works this example related to comunication between a parent and a child component.
So I have this PARENT COMPONENT. This component is used to show a list of items (each item is represend by the child component). Interacting with this component I can add and remove items from this list of items.
This is the parent Component :
@Component({
selector: 'app-products',
templateUrl: './products.component.html'
})
export class ProductsComponent {
productName = 'A Book';
isDisabled = true;
products = ['A Book', 'A Tree'];
constructor() {
setTimeout(
() => {
this.isDisabled = false;
}, 3000)
}
onAddProduct() {
this.products.push(this.productName);
}
onRemoveProduct(productName: string) {
this.products = this.products.filter(p => p !== productName);
}
}
And this is its template :
<h1>My Products</h1>
<input *ngIf="!isDisabled" type="text" [(ngModel)]="productName">
<button *ngIf="!isDisabled" (click)="onAddProduct()">Add Product</button>
<app-product
(productClicked)="onRemoveProduct(product)"
*ngFor="let product of products"
[productName]="product">
</app-product>
Then I have the child component representing a single item of the list handled by the parent component. This is the child Component :
@Component({
selector: 'app-product',
templateUrl: './product.component.html',
styleUrls: ['./product.component.css']
})
export class ProductComponent {
@Input() productName: string;
@Output() productClicked = new EventEmitter();
onClicked() {
this.productClicked.emit();
}
}
And this is te children template :
<article class="product" (click)="onClicked()">
<div>{{ productName }}</div>
<p>An awesome product!</p>
</article>
Ok, now I have some doubts about how these 2 components interact together:
In the parent component template :
<app-product
(productClicked)="onRemoveProduct(product)"
*ngFor="let product of products"
[productName]="product">
</app-product>
that is referring to the child component (labeled by app-product).
It seems to me that basically I am iterating on the products list defined into the parent component class (an array of strings) and that each of these string is passed to the productName
variable defined into the child component class, to do it I am using the @Input()
decorator on this property in the child component class:
@Input() productName: string;
Basically this @Input() decorator hallow the parent component to "inject" the value into the child component property at each iteration.
Is it? or am I missing something?
Then I have the behavior that handle the item removal from the items list: when an element of the list is clicked (implemented by the child component). This element is removed from the list (and so from the page).
How it works (my idea):
Each element is represented by this code in the child component view:
<article class="product" (click)="onClicked()">
<div>{{ productName }}</div>
<p>An awesome product!</p>
</article>
When an object is clicked it is performed the onClicked()
event into the child component class. I can't remove the selected object directly from the child component class because the array of items is defined into the parent component class. So this method emit an event:
onClicked() {
this.productClicked.emit();
}
having "type" productClicked (is it an event type or what?). This event is received in the parent component view:
(productClicked)="onRemoveProduct(product)"
that call the onRemoveProduct(product)
method that remove the object having this name from the array.
Is it correct or in my reasoning am I missing something?
Another doubt is: is it a neat and correct way to handle events and this kind of situation?
Upvotes: 0
Views: 95
Reputation: 99
You are right in both cases !
And according to the angular guide, this is a correct way to handle communication between parent/child components.
Upvotes: 0