Is there a way to effectively sort through Firebase database entries using Angular based on checkbox selection?

I am working on an event page where all events are displayed with a category field. This is how my database structure looks:

category:
  - categoryName

events:
  - eventName
  - category.id (stores the category id)

My goal is to initially display all events and then filter events based on checkbox selections by users. When a checkbox is checked, I want to show only events belonging to that category, and when unchecked, display all events again. I would appreciate any help as I'm new to Angular.

Thank you :)

events.service.ts

categories = null;
subscription;

/** Get Categories */
  getEventCategories() {
    if (!this.categories) {
      this.subscription = this.db
        .collection('categories')
        .valueChanges({ idField: 'id' })
        .subscribe(categories => (this.categories = categories));
    }
  }

/** Get Category Vise Events */
  getCategoryViseEvents(category: string) {
    return this.db
      .collection('events', ref => ref.where('eventCategory', '==', category))
      .valueChanges({ idField: 'id' });
  }

event.component.ts

import { Component, OnInit } from '@angular/core';
import { EventsService } from 'src/app/services/events.service';

@Component({
  selector: 'app-events-list',
  templateUrl: './events-list.component.html',
  styleUrls: ['./events-list.component.css']
})
export class EventsListComponent implements OnInit {
  events: any;
  mobile = false;
  loading = true;

  constructor(public eventService: EventsService) {}

  ngOnInit(): void {
    if (window.screen.width === 375) {
      // 768px portrait
      this.mobile = true;
    }

    this.eventService.getEventCategories();
    this.eventService.getAllEvents().subscribe(ev => {
      this.loading = false;
      this.events = ev;
    })
  }

  getCategory($event) {
    this.loading = true;
    if ($event.target.checked) {
      this.eventService.getCategoryViseEvents($event.target.id).subscribe(events => {
        this.events = events;
        this.loading = false;
      })
    } else {
      this.loading = false;
    }
  }
}

**event.component.html

<input
  type="checkbox"
  class="custom-control-input"
  [id]="category.id"
  (change)="getCategory($event)"/>

Answer №1

Establish a new object named allEvents within your service component. Although I cannot locate the function getAllEvents, it is crucial that it populates its own result in the allEvents property before returning. This can be achieved by subscribing to the observable twice, once in the service and once in the component.

events.service.ts

categories = null;
subscription;
allEvents: Array<any> = [] // Store events here from getAllEvents

/** Get Categories */
getEventCategories(sendCategoriesCallback: function) {
    if (!this.categories) {
      this.subscription = this.db
        .collection('categories')
        .valueChanges({ idField: 'id' })
        .subscribe(categories => {
            this.categories = categories
            sendCategoriesCallback(this.categories)
        });
    }
}

/** Get Category Specific Events */
getCategoryViseEvents(category: string) {
    return this.allEvents.filter(event => event.category == category)
}

event.component.ts

In the snippet below, notice that most of the getCategoryVise.. has been removed as the filter no longer returns an Observable (it's instantaneous).

import { Component, OnInit } from '@angular/core';
import { EventsService } from 'src/app/services/events.service';

@Component({
  selector: 'app-events-list',
  templateUrl: './events-list.component.html',
  styleUrls: ['./events-list.component.css']
})
export class EventsListComponent implements OnInit {
  events: any;
  mobile = false;
  loading = true;

  constructor(public eventService: EventsService) {}

ngOnInit(): void {
    if (window.screen.width === 375) {
      // 768px portrait
      this.mobile = true;
    }

    this.eventService.getEventCategories((categories) => {
        this.categories = categories
    });

    this.eventService.getAllEvents().subscribe(ev => {
      this.loading = false;
      this.events = ev;
    })
  }

  getCategory($event) {
    this.loading = true;
    if ($event.target.checked) {
    this.events = this.eventService.getCategoryViseEvents($event.target.id)
  }
}

event.component.html

I have included the *ngFor directive behavior here:

<input
  *ngFor="let category of categories"
  type="checkbox"
  class="custom-control-input"
  [id]="category.id"
  (change)="getCategory($event)"/>

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

Leveraging a React hook within a Next.js API route

I am looking for a way to expose the data fetched by a React.js hook as a REST endpoint using Next.js. To create a REST endpoint in Next.js, I can easily use the code below in pages/api/index.tsx export default function handler(req: NextApiRequest, res: N ...

How can I access a DOM element in an AngularJS 2 TypeScript file?

As a newcomer to AngularJS, I am attempting to add a spinner as a background to all images on my website. Since there are multiple images, using a single variable like isLoaded in the TypeScript file is not feasible. Here is how I am implementing it in th ...

Resetting all services and components in Angular 2 navigation

After extensive searching on various platforms, I have yet to find a satisfactory explanation for my current issue. I am in the process of developing a basic Angular 2 application that consists of a RouterModule, a simple Service, and a Component. Below a ...

Ways to display a US map using d3.js with state names positioned outside each state and pointing towards it

Currently, I am working with d3.js and d3-geo to create a map of the USA. My goal is to display the names of some states inside the state boundaries itself, while others should have their names positioned outside the map with lines pointing to the correspo ...

How to manually resolve a type by its string or name in Angular 2

I'm facing a challenge. Is it possible to resolve a component manually with just its name known? Let's say I have a string variable that holds the name of a component, like "UserService". I've been exploring Injector and came across method ...

Leverage properties within the storybook component template

When utilizing a class component in a narrative, it allows you to transmit properties as arguments: const Template: Story<MyComponent> = (args) => ({ props: args, component: MyComponent, }) export const Default = Template.bind({}); export co ...

What is the most effective way to access a variable from a service in all HTML files of Angular 2/4 components?

In my angular 4 project, I have an alert service where all components can set alerts, but only specific components display them in unique locations. My question is: how can I access a variable from this service across all HTML files? The structure of my s ...

Enhance your images with the Tiptap extension for customizable captions

click here for image description I am looking to include an image along with an editable caption using the tiptap extension Check out this link for more information I found a great example with ProseMirror, but I'm wondering if it's possible ...

A comprehensive guide on organizing JavaScript files within an Angular project

In the process of building my MEAN app, I have structured my folders in the following way: I have included a js file in /angular/src/assets/js for jQuery functionalities. To achieve this, I utilized npm to install jQuery. Now, I am faced with the task o ...

Issue with TypeScript when using destructuring on an object

When attempting to destructure data from an object, I encountered the error message Property XXXX does not exist on type unknown. This issue arose while using React Router to retrieve data. let {decoded, reasonTypes, submissionDetails} = useRouteLoaderDa ...

Firebase is causing an issue: Error message states that a module cannot be found, and the default condition should be the

For some time now, I've been utilizing AngularCrashlytics(from @angular/fire). However, this morning I encountered issues with both build and ng serve, resulting in the error shown below. Can anyone assist me in resolving this? https://i.stack.imgur. ...

Customizing the Switch component individually for each item fetched from an API in React Native

I'm struggling with setting the switch button individually for each item in my API. Despite trying multiple solutions, none of them seem to work for me. const results = [ { Id: "IySO9wUrt8", Name: & ...

Retrieving the latest status array by index using Typescript in Angular

Need help with this code logic. I am working on an array and function : import { Component } from '@angular/core'; @Component({ selector: 'my-app', templateUrl: './app.component.html', styleUrls: [ './app.compon ...

Resolve ESLint errors in _document.tsx file of next.js caused by Document<any> and ctx.renderPage = () with TypeScript usage

maxbause took the initiative to create a comprehensive boilerplate project for Next.js, complete with GraphQL and styled components in TypeScript. Check out the project here However, upon integrating ESLint into the project, I encountered several warning ...

Display a FullCalendar showcasing events for the next 30 days

I am currently working with the FullCalendar library and I have a unique request. I need to create a rolling 30-day view using the month grid style, complete with day headers. Additionally, I need the flexibility to set the starting day in the grid. For ...

Error in backend request originating from an Angular 2 source

I have an email for user verification that includes a link to my angular 2 route localhost:4200/verify/{userId}. When the user clicks on this link, it directs them to the angular 2 route where I extract the userId from the URL and pass it into my service. ...

How to attach an event listener to an input element using Angular

I am looking to add a listener to an input element that will be triggered every time the user changes the input values. The goal is to display the current values chosen by the user. Example HTML template: <div id="idDoseLabel1" class="da ...

Using an external npm module in TypeScript can result in the tsc output directory being modified

In my TypeScript project, I have set up the build process to generate JavaScript files in the ./src/ directory. Everything works smoothly when building against existing npm modules, such as Angular 2 imports. However, I encountered a strange issue when I ...

Encountering a timeout issue with the Sinch API within an Angular 2 project during the onCallProgressing

We successfully integrated Sinch into our angular 2 web application. Most functionalities are working perfectly, except for the user calling feature using the sinch phone demo. When the application is in the foreground, the call rings and connects withou ...

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 ...