Here's plunker of what might work for you:
https://plnkr.co/edit/S47fBh2xdT1gp2zrznk4?p=preview
Instead of passing the data from parent to child component, both parent and child component will use service to get the data.
Parent Component:
import { Component, OnInit } from '@angular/core'; import { Product } from './product' import { ProductsService } from './products.service'; @Component({ selector: 'app-appliances-product-card', template: ` <div class="container-fluid"> <button (click)="filterProduct('Type 1')">Filter Type 1</button> <button (click)="filterProduct('')">Clear Filter</button> <div class="col-sm-9"> <app-products-card></app-products-card> </div> </div> ` }) export class AppliancesProductCardComponent implements OnInit { products: Product[]; constructor(private _productsService: ProductsService){ } filterProduct(type: string) { this.products = this._productsService.filterProduct(type); } ngOnInit() { this.products = this._productsService.getAllProducts(); } }
Child Component:
import { Component, OnInit, Input } from '@angular/core'; import { Product } from './product'; import { ProductsService } from './products.service'; @Component({ selector: 'app-products-card', template: ` <h1>Product Card</h1> <div *ngFor="let product of products">{{product.name}} - {{product.type}}</div> ` }) export class ProductsCardComponent implements OnInit { constructor(private _productsService: ProductsService){ } ngOnInit() { this.products = this._productsService.getAllProducts(); this._productsService.filteredProducts.subscribe(products => { console.log(products); this.products = products }); } }
Service:
import { EventEmitter, Injectable } from '@angular/core'; import { Product } from './product'; export class ProductsService { filteredProducts = new EventEmitter<Product[]>; private products: Product[] = [ { id: 1, name: 'Product 1', price: 10.50, type: 'Type 1' }, { id: 2, name: 'Product 2', price: 15.50, type: 'Type 1' }, { id: 3, name: 'Product 3', price: 1.50, type: 'Type 2' }, { id: 4, name: 'Product 4', price: 100.50, type: 'Type 3' } ]; getAllProducts(): Product[] { return this.products.slice(); } filterProduct(type: string): Product[]{ let filteredProducts = this.products.filter(p => !type || p.type == type).slice(); this.filteredProducts.emit(filteredProducts); } }
I came across similar problems when I first started writing angular application. Passing data from parent to child component all the time is not a manageable way to write application. Specially if it's a big application with too many nested components.
In this example, I'm using the services and event emitter (both part of angular framework) to provide relevant data to both the child and the parent component.
One way to improve the code is to use rxjs. This is what angular event emitter uses behind the scene.
And even more advanced solution is to use ngrx/store (redux library for Angular). This is particularly suited for huge applications.
No matter which solution you choose, the idea is to have a single place to maintain the state of the application and avoid nesting data too much.