Displaying search results in various Angular components

On my home page (homePageComponent), I have a search feature. When the user clicks on the search button, they are redirected to a different page called the search list page (searchListComponent). Within the searchListComponent, there is another component called the search card component (searchCardComponent) where all the search results are displayed. I attempted to pass the search text from the homePageComponent to the searchCardComponent using an event emitter, but unfortunately, the data is not being passed successfully. I would greatly appreciate any assistance with this issue.

Below is a snippet of sample code:

homePageComponent

HTML (Product A)

     <ng-select
              class="col-md-5 solution-list-dropdown"
              [items]="productType$ | async"
              [addTag]="true"
              [(ngModel)]="selectedSolutionId"
              bindLabel="description"
              bindValue="id"
              placeholder="Select"
              [clearable]=true
              [searchable]=true
              [dropdownPosition]="'down'"
              [ngClass]="{ 'dropdown-is-invalid': submitted && f.category.errors }">
           </ng-select>
<button class="red-button"  (click)="searchRedirection(selectedSolutionId)">
          Search
        </button>

Typescript

  @Output() searchValue = new EventEmitter<string>();

   public searchRedirection(selectedSolutionId: string) {
      this.searchValue.emit(selectedSolutionId);
      this.router.navigate(['/category/' + selectedSolutionId]);
    }

SearchListComponent

HTML

<div class="container-fluid product-card-container p-0" id="hor-divider">

    <div class="product-list">
      <app-product-card (searchValue)="onApplyEvent($event)" *ngFor="let product of products | filter:searchText | filter:filterText" [product]="product">
      </app-product-card>
    </div>

</div>

Typescript

  onApplyEvent(event: any): any {
    console.log('event : ' + event);
  }

In this scenario, I expected the console log to print "event: Product A", so that I could use it to bind the value into *ngFor. Any guidance on resolving this issue would be highly appreciated.

Answer №1

If you want to pass data between two components in Angular, a good approach is to use a shared service.

The shared service can utilize a subject or eventEmitter (preferably a subject), where the home page component emits the subject and the search card component subscribes to it to receive the data.

Here's an example of how to set up the shared service:

shared.service.ts

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable({providedIn: 'root'})

export class SharedService {

  searchSubject = new Subject<String>(); 
}

In the home component, when a solution is selected, emit it to the shared service. You can use (change) or (ngModelChange) on your list in the HTML to detect changes and emit the subject accordingly.

For example, in the home component HTML:

(ngModelChange)="onSelectSolution()"

And in the TypeScript file:

constructor(private sharedService: SharedService) { }

onSelectSolution() {
  this.sharedService.searchSubject.next(this.selectedSolutionId);
}

Then, in the search card component:

import { OnInit, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs';

export class SearchCardComponent implements OnInit, OnDestroy {
  subscription: Subscription 

  constructor(private sharedService: SharedService){}

  ngOnInit() {
    this.subscription = this.sharedService.searchSubject.subscribe((mySearch: String) => {
      // Receive the search data passed from the home component
    });
  }

  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}

For more information on the difference between (change) and (ngModelChange), check out this link: difference between (change) and (ngModelChange)

Answer №2

When it comes to using an event emitter, the way you have declared it may not work as intended because it can only be accessed by the parent component of homePageComponent using the @Output decorator. One possible solution is to create a separate events class that can be imported into both components – one for emitting and the other for receiving. However, this approach is considered poor practice. A better alternative would be to either send the search word as a query parameter in the route or utilize a shared service with a BehaviorSubject object to store and transmit the last emitted value.

this.router.navigate(['/category'], { queryParams: { selectedSolutionId: selectedSolutionId } });

To retrieve the value in SearchListComponent, you would need to:

import { ActivatedRoute } from '@angular/router';
.....
constructor(private route: ActivatedRoute) { }
ngOnInit() {
this.route.queryParams
  .subscribe(params => {
    this.selectedSolutionId = params.selectedSolutionId;
    //Then, you can pass this.selectedSolutionId as @Input to the app-product-card component
    console.log(this.selectedSolutionId );
  });
}

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

Is it possible to transform an array into a JSON file and securely store/upload it in an AWS S3 bucket?

Recently, I started exploring aws and its capabilities. Currently, my focus is on developing a web application that allows users to input text in two separate fields. Subsequently, this text will be converted into a Json file and stored in the S3 bucket. ...

Steer clear of encountering the "$digest already in progress" issue

A custom directive named 'myPagination' has been implemented, which encapsulates the functionality of the UI Bootstrap's pagination directive. angular.module('my-module') .directive('myPagination', ['$filter' ...

What is the best way to load an index.js file within a plugin framework?

I currently have an isolated index.js file located at plugins/some_plugin/index.js After attempting to run require(path_to_index.js) in my application, I encounter a 'cannot find modules' error message. This issue is understandable as the "some ...

Instructions on transferring information from the app.component to its child components

I am currently working with Angular 6 and I have a specific requirement. I need to send data retrieved from an external API in my app.component to other child components. Instead of repeatedly calling the common API/service in every component, I want to ma ...

When 'Interval.after' is invoked within the library, Luxon throws an error message stating "Invalid Interval."

Encountering a strange issue with Luxon when the Interval.after method is invoked within the library. const interval = Interval.after(dateTime, duration); The following log pertains to the application DateTime__Duration, with the second line representing ...

Supply mandatory argument along with varying arguments to the function

I have a function that requires one parameter and a dynamic set of additional parameters. I am passing an array of blobs to the function. Below is a simplified version of the function: function test(directory, blob0, blob1) { for (var argumentIndex = 1; ...

The error TS2339 occurs because the property 'remove' is not found in the type 'Document<unknown>'

I encountered an error while using my application Runtime Error: TSError: ⨯ Unable to compile TypeScript: src/controllers/notes.ts:134:20 - error TS2339: Property 'remove' does not exist on type 'Document<unknown, {}, { createdAt: Nat ...

Analyzing string values in Cypress

When attempting to compare two values within a page and make an assertion, my goal is to retrieve the value of one text element and compare it with another value on the same page. While I find this process straightforward in Java/selenium, achieving the ...

Unable to retrieve HTML content through a Node.js server

I created a HTML webpage that includes .css, images and JavaScript files. However, when I start my node server using the command below: app.get('/', function(req, res){ res.sendFile(__dirname + '/index.html'); }); The webp ...

Having difficulties fetching data from Express server to React

My current project involves fetching data from an Express server to a React application using the Fetch API. The Express server interacts with a PostgreSQL database to retrieve relevant data that should be sent to the React frontend. The code snippets bel ...

What is the best way to style MUI's Button component with a link to appear like a standard button?

I have a Button that allows users to download a file with a specific filename. Here is the code I used: <Button color='primary' href=`/apiproxy/objects/${id}/subobjects` LinkComponent={React.forwardRef((props, ref) => <Link {...pro ...

Tips for implementing react-select types in custom component development

Currently, I'm in the process of developing custom components for DropdownIndicator to be used on react-select with Typescript. However, I am encountering difficulties with the component's type due to my limited experience with Typescript. I wou ...

Obtain the Enum's Name in TypeScript as a String

I am currently looking for a solution to transform the name of an enum into a string format. Suppose I have the following Response enum, how can I obtain or convert 'Response' into a string? One of my functions accepts any enum as input and requi ...

Applying ngClass to a row in an Angular material table

Is there a way I can utilize the select-option in an Angular select element to alter the css-class of a specific row within an Angular Material table? I have successfully implemented my selection functionality, where I am able to mark a planet as "selecte ...

Building applications for platform iOS is not supported on this operating system

I'm currently exploring the features of NativeScript + Angular + SQLite for building a mobile application, and I am referencing this video as a guide. However, when I reached the 3:00 mark, it instructed me to execute the command tns platform add ios ...

having trouble transferring the password field in PHP to phpMyAdmin

My HTML form collects the user's first name, last name, username, and password. I am trying to upload this data to my local phpMyAdmin, but I'm facing an issue with storing the password in the database. Below is my HTML code: <input type="te ...

Issue with Electron dialog.showOpenDialog() Filters malfunctioning

Recently, I've been working on a modified version of an IDE on GitHub and encountered a major issue where the files were being saved to cookies instead of the computer. This prompted me to find a way to save and open files efficiently. While I managed ...

Is there a way for me to reach the ngFor variable within a different ngFor loop?

Here is an example code snippet to display user details. Currently, we have only one user and three permissions in an array: 1) Users = [{'FirstName':'John','permission':['masters','transactions']}] 2) p ...

"What are the reasons for encountering a '404 not found' error with Django when accessing a

I recently developed a Django script that utilizes a Python parser to navigate the web. I have set up AJAX to send requests to this Django script, but I am encountering a 404 error for the URL when the Ajax runs. Can you help me understand why this is occu ...

Transform the hue of symbols within D3-legend

I am attempting to modify the appearance of symbols in a legend. The variable below represents the available symbol types: var symbolTypes = { "triangleUp": d3.svg.symbol().type("triangle-up"), "circle": d3.svg.symbol().type("circle") }; I use this varia ...