Hi I am new to the angular and I am trying to create an anuglar checkbox filter pipe to filter my products data!Here I have created a colors for checkboxes in my .ts file (I have not included the code which is not relevant to this issue)
public colors: any[] = [
{
id: 1,
color: "Black",
selected: true,
},
{
id: 2,
color: "Green",
selected: true,
}
]
I am using a pipe for the checkboxes -
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'selectBrand'
})
export class SelectBrandPipe implements PipeTransform {
transform(check: any, checked?: any): any {
console.log('checked', checked);
return checked ? check.filter(sal => sal.type === checked) : check;
}
}
In my HTML file -
<form>
<div class="form-check brand-checkbox" *ngFor="let col of colors">
<input class="form-check-input"
type="checkbox"
value="{{col.id}}"
id="{{col.id}}"
name=""
[(ngModel)]="col.selected">
<label class="form-check-label" for="{{col.id}}">
{{col.productColor}}
</label>
</div>
</form>
<div class="shop" *ngFor="let prod of productListShow">
<div class="col-md-4" *ngFor="let product of prod.product | selectBrand: colors">
<h5>{{product.productName}}</h5>
</div>
</div>
I am getting my products data from a service -
{
id: 1,
productName:'Products',
product: [
{
productId: 1,
productName: 'Shirt 1',
productColor: 'Green',
},
{
productId: 2,
productName: 'Shirt 2',
productColor: 'Black',
},
],
},
When the code runs all the checkboxes are selected and I see no products and in my console log. I am getting -
checked
(2) [{…}, {…}]
0
:
{id: 1, productColor: "Black", selected: true}
1
:
{id: 2, productColor: "Green", selected: true}
length
:
2
__proto__
:
Array(0)
you are passing products Array as check and colors Array as checked into your pipeTransform function. Then you check if product.type (which btw does not exist according to your products model definition) is equal to colors Array. I guess this is not what you want to check.
Try with:
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'selectBrand',
pure: false
})
export class SelectBrandPipe implements PipeTransform {
transform(products: any[], colors: any[]): any {
const activeColors = colors.filter(c => c.selected).map(c => c.color)
console.log('checked colors', activeColors.join(","));
return products.filter(p => activeColors.includes(p.productColor));
}
}
btw: if you really want to use a pipe for filtering, you need a impure pipe which is not recommended due to performance reasons.
i recommend to filter the products only when user changes the checkbox status by adding (ngModelChange) to the checkbox input-element, e.g:
<input class="form-check-input"
type="checkbox"
value="{{col.id}}"
id="{{col.id}}"
name=""
[(ngModel)]="col.selected"
(ngModelChange)="filterProducts()">
In your component typescript add a function filterProducts which does the filtering:
public filterProducts(): void {
const filteredProductArray = new Array<any>();
const activeColors = this.colors.filter(c => c.selected).map(c => c.color);
this.productListShow.forEach(prod => {
const filteredSubProducts = prod.product.filter(p => activeColors.includes(p.productColor));
if(filteredSubProducts.length > 0){
const clonedProduct = Object.assign({}, prod);
clonedProduct.product = filteredSubProducts;
filteredProductArray.push(clonedProduct);
}
});
this.filteredProducts = filteredProductArray;
}
then use filteredProducts in ngFor instead of productListShow