Troubleshooting issue with multiple pipe filters in an array of objects in Angular 5

I am currently facing an issue with my Angular component that includes 3 filters (category, rating, and price). When I select these filters, I should only display the relevant data. To achieve this, I have created a Pipe and passed in all three selected values. The category filter is functioning correctly, but the rating and price filters are not working as expected.

Json data:

"allBusiness": [    
        {
            "category": "XYZ",
            "description": "something something",
            "business": [
             {
                "type": "Store",
                "rating": 4,
                "price" : "$"
             },
             {
                "type": "Store",
                "rating": 3,
                "price" : "$"
             },
             {
                "type": "Store",
                "rating": 5,
                "price" : "$$"
             }           
             ]

        },
        {
            "category": "ABC",
            "description": "Testing",
            "business": [
             {
                "type": "Online",
                "rating": 3,
                "price" : "$"
             },
             {
                "type": "Store",
                "rating": 2,
                "price" : "$"
             },
             {
                "type": "Store",
                "rating": 1,
                "price" : "$$"
             }           
             ]

        }
]

FilterPipe.ts:

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'filter'
})
export class FilterPipe implements PipeTransform {

  transform(allBusiness: any[], selectedCategory: string, selectedRating: number, selectedPrice: string): any {
    if (allBusiness && allBusiness.length){
        return allBusiness.filter(item =>{
            if (category && item.category.indexOf(selectedCategory) === -1){
                return false;
            }
            if (rate && item.business.filter(rt => rt.rating != selectedRating)){
                return false;
            }
            if (price && item.business.find(pr => pr.price != selectedPrice)){
                return false;
            }
            return true;
       })
    }
    else{
        return items;
    }
  }
}

Any help would be greatly appreciated.

Answer №1

We utilize two distinct filters for both the outer and inner lists. These are categorized as

allBusinessFilterBy: {category?: string}
and
businessFilterBy: {rating?: number; price?: string;}
.

interface BusinessFilterBy {
  rating?: number;
  price?: string;
}

interface AllBusinessFilterBy {
  category?: string;
}


function isNill(item) {
  return item === undefined || item === null || (item !== item);
}

function isBusiness(item, filterBy: BusinessFilterBy) {
  return (isNill(filterBy.rating) || item.rating === filterBy.rating) && (isNill(filterBy.price) || item.price === filterBy.price);
}

function isAllBusiness(item, filterBy: AllBusinessFilterBy) {
  return isNill(filterBy.category) || item.category === filterBy.category;
}

function filterBusiness(item, businessFilterBy: BusinessFilterBy) {
  return [{
    ...item,
    business: item.business.filter(businessItem => isBusiness(businessItem, businessFilterBy))
  }];
}

function transform(allBusiness = [], allBusinessFilterBy: AllBusinessFilterBy = {}, businessFilterBy: BusinessFilterBy = {}) {
  if (!allBusiness && !allBusiness.length) {
    return allBusiness;
  }
  return allBusiness.reduce((acc, item) => [...acc, ...isAllBusiness(item, allBusinessFilterBy) ? filterBusiness(item, businessFilterBy) : []], []);
}

Answer №2

When you mention I have to display only the relevant information in terms of sorting by rating or price, I may need clarification:

  • To exclude an item in allBusiness if none of its entries in the business array contain a specific rating and price.
  • To include an item only if it has at least one entry in the business array with the specified rating and price.

If my understanding is correct, this could be implemented as follows:

return allBusiness.filter(item => 
   (selectedCategory && item.category && item.category.indexOf(selectedCategory) > -1)
   && (selectedRating && item.business && item.business.length > 0 && item.business.find(rt => rt.rating == selectedRating))
   && (selectedPrice && item.business && item.business.length > 0 && item.business.find(pr => pr.price == selectedPrice)))

If the goal is to filter allBusiness so that it includes an entry only when all items in its business array match the specified rating and price, you can use the following logic:

return allBusiness.filter(item => 
   (selectedCategory && item.category && item.category.indexOf(selectedCategory) > -1)
   && (selectedRating && item.business && item.business.length > 0 && !item.business.find(rt => rt.rating != selectedRating))
   && (selectedPrice && item.business && item.business.length > 0 && !item.business.find(pr => pr.price != selectedPrice)))

Please note:

find() retrieves the first item in an array that matches the provided condition. If no items match, it returns undefined.

filter(), on the other hand, creates a new array containing only those items from the original array that meet the specified condition. If no items match, it returns an empty array.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Utilize an array of observables with the zip and read function

I'm struggling with putting an array of observables into Observable.zip. I need to create a function that reads values from this dynamically sized array, but I'm not sure how to go about it. Does anyone have any suggestions? import {Observable} ...

Inquiry regarding the implementation of DTO within a service layer parameter

I have a query regarding the choice of service layer to use. // 1 export class SomeService{ async create(dto:CreateSomeDto) {} } or // 2 export class SomeService{ async create(title: string, content: string) {} } It appears that most individuals opt ...

Error in Typescript compilation in Visual Studio Team Services build

I am currently working on an angular2 web application using Typescript 2.0. I have successfully installed version 2.0 locally in my Visual Studio and updated the tag for Typescript version in my project. The local build in VS works perfectly fine, but when ...

Enroll a nearby variable "Data" to an Observable belonging to a different Component within an Angular application

Looking to update the HTML view using *ngIf, depending on a local variable that should change based on an observable variable from a shared service. HTML <div class="login-container" *ngIf="!isAuthenticated"> TypeScript code for the same componen ...

The Angular custom modal service is malfunctioning as the component is not getting the necessary updates

As I develop a service in Angular to display components inside a modal, I have encountered an issue. After injecting the component content into the modal and adding it to the page's HTML, the functionality within the component seems to be affected. F ...

What are the steps for utilizing the useReducer Hook with TypeScript?

I have successfully converted a React app to Typescript, but I am facing an issue with the useReducer Hook. The error message I'm getting is preventing me from moving forward. I have attempted different approaches to passing TypeScript interfaces in ...

What is the best way to include type within a nested object?

How should I properly define types for a nested object structured like the example below? const theme: DefaultTheme = { color: { primary: '#5039E7', secondary: '#372E4B', heading: '#4D5062', }, ...

Prevent selection of weekends on mat-date-range in Angular

Is there a way to disable weekends on a calendar using date range? I've tried but can't seem to get it to work. Any suggestions? The Issue Can't bind to 'matDatepickerFilter' since it isn't a known property of 'input&a ...

Class-validator: eliminate a field during validation depending on the value of another field

When using class-validator in conjunction with NestJS, I have successfully implemented the following: export class MatchDeclineReason { @IsString() @IsEnum(MatchDeclineReasonType) @ApiProperty() type: MatchDeclineReasonType; @ValidateIf(reason = ...

Steps for displaying a loader after refreshing data using queryClient.invalidateQueries:1. Utilize the query

I am currently working on a project where I need to redirect to a specific page after updating an item. While the code is functioning correctly, I have encountered an issue with the loader not displaying. export const useUpdateStatusArchiveSurvey = () => ...

A step-by-step guide on enhancing error message handling for Reactive forms in Angular

Here is a code snippet that I'm working on: public errorMessages; ngOnInit(): void { this.startErrorMessage(); } private startErrorMessage() { this.errorMessages = maxLength: this.translate.instant(' ...

PlateJS: Difficulty in inserting images - Screen remains empty when trying to add images using the Image Element

I incorporated the Image Element component using the command npx @udecode/plate-ui@latest add image-element This action added the caption, media-popover, and resizable components to my setup. When referencing Platejs documentation, everything appears as ...

Struggling to figure out webhooks with Stripe

I have encountered a strange issue while using Stripe webhooks to process payments on my website. When I set the currency to USD, it prompts me to provide an address outside of India, which is expected. However, when I change the currency to INR, the addre ...

Oops! The Angular compiler is throwing an error because it needs TypeScript version greater than or equal to 3.1.1 and less than 3.2.0, but it found version 3

Encountering a curious issue here ERROR in The Angular Compiler demands TypeScript version be greater than or equal to 3.1.1 and less than 3.2.0, but it detected version 3.2.1 instead. Appears that Typescript received an update which is conflicting wit ...

Tips for utilizing generic object utilities for objects defined by interfaces in Typescript

I am facing an issue with my code where I have defined an object with an interface and a utility function to clean up the object by removing undefined properties. However, when I try to pass this object to the utility function, Typescript throws an error. ...

Require assistance with transforming a JSON string into an object

I've been struggling with converting the JSON object returned from the service to the Directory class. The issue is that the Directory class has an 'expanded' property which is not present in the JSON object. I've tried various methods ...

Start URL is not being controlled or registered by the service worker

Manifest Tab in Chrome: https://i.sstatic.net/vLJKJ.png I can't find the service worker in the Chrome Service Worker tab either: https://i.sstatic.net/JAqIk.png This is the content of my manifest.json file: { "short_name": "shortname", "n ...

Access the PrimeNG context menu in Angular 2 by using code to open it

I am trying to open the context menu provided by PrimeNG in a table by using a button and right click. Although I have found the methods 'toggle' and 'show' in the component, the menu is not opening. Even after setting a new position fo ...

The interface in Angular fails to refresh after the information is modified within its scope

It seems like I might be overlooking something. Currently, my subscription is set up in a way that local changes made with the typeWriter function inside the component do not update the UI accordingly. The UI only updates when changeDetectorRef.detectCha ...

Check the connectivity of Angular 2 application

I currently have an Angular 2 application running on one server, and a Java application on another server. My goal is to be able to ping the Angular application from the Java application in order to check its status (whether it is up or down). Would it b ...