Using a single Material Autocomplete input to handle two values within Angular

Looking to implement a search feature using Material's autocomplete that can filter by either user name or user ID. The current implementation is partially functional in this Stackblitz.

When selecting a user name from the autocomplete options with a mouse click, it correctly redirects to the user detail page. However, when using keyboard arrows to select and submit with 'Enter', it displays [object Object] in the input field instead of the actual Name. How can I modify this to display the user name?

Furthermore, is there a way for the autocomplete to display IDs instead of names if the user inputs numeric values?

HTML:

<p>Search Users by Name or ID</p>
<form [formGroup]="searchForm" (ngSubmit)="onSubmit()">
  <input type="text" [matAutocomplete]="auto" [formControl]="searchControl" />
  <mat-autocomplete #auto="matAutocomplete">
    <mat-option (click)="onSubmit()" *ngFor="let option of (filteredOptions | async)" [value]="option">
      {{ option.name }}
    </mat-option>
  </mat-autocomplete>
  <input type="submit" style="display: none;">
</form>

TS:

import { Component, OnInit } from "@angular/core";
import { Observable } from "rxjs";
import { map, startWith } from "rxjs/operators";
import { Router } from "@angular/router";
import { FormGroup, FormControl } from "@angular/forms";
import { User } from "../user";
import { UserService } from "../user.service";

@Component({
  selector: "app-users",
  templateUrl: "./users.component.html",
  styleUrls: ["./users.component.css"]
})
export class UsersComponent implements OnInit {
  filteredOptions: Observable<User[]>;
  users: User[] = [];
  options: User[];
  searchControl = new FormControl();
  searchForm = new FormGroup({
    searchControl: this.searchControl
  });

  getUsers(): void {
    this.users = this.UserService.getUsers();
  }

  constructor(public router: Router, private UserService: UserService) {}

  ngOnInit() {
    this.getUsers();

    this.options = this.users;

    this.filteredOptions = this.searchControl.valueChanges.pipe(
      startWith(""),
      map(value => this._filter(value))
    );
  }

  private _filter(value: string): User[] {
    const filterValue = value;
    return this.options.filter(
      option =>
        String(option.id)
          .toLowerCase()
          .indexOf(filterValue) > -1 ||
        option.name.toLowerCase().indexOf(filterValue) > -1
    );
  }

  // Search bar
  onSubmit() {
    let userId = this.searchControl.value.id;
    this.router.navigate(["user-details", userId]);
  }
}

Answer №1

It might be beneficial to utilize the displayWith property of AutoComplete in this scenario. Your updated code should look like this:

HTML:

<mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFunction">
    <mat-option (click)="onSubmit()" *ngFor="let option of (filteredOptions | async)" [value]="option">
      {{ option.name }}
    </mat-option>
</mat-autocomplete>

In TypeScript:

displayFunction(user: User): string {
    return user && user.name ? user.name : "";
}

View Demo on StackBlitz

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

Ways to emit a value from an observable once it is defined?

Is it feasible to create an observable that can wrap around the sessionStorage.getItem('currentuser')? This way, calling code can subscribe and retrieve the value only after it has been set in the sessionStorage. Do you think this is achievable? ...

Transmit JSON from PHP to an autocomplete feature and include a data attribute in the input field

[{ "id": "39", "name": "John Doe", "code": "060400000" }] $(document).on("input", ".autocomplete", function(event) { var name = $(this).prop('id').split('_').pop(); $(".autocomplete").autocomplete({ source: function(request, respo ...

Tips for parsing through extensive JSON documents containing diverse data types

In the process of developing an npm package that reads json files and validates their content against predefined json-schemas, I encountered issues when handling larger file sizes (50MB+). When attempting to parse these large files, I faced memory allocati ...

Cannot utilize remote.require() in TypeScript due to compatibility issues

Recently, I've been facing a frustrating issue while developing an Electron application in TypeScript. I've been trying to execute a module from a renderer process using the code snippet below: import { remote } from 'electron' const ...

Tips on expanding properties for Material-UI components with Typescript?

My goal is to enhance the props of the Button component from Material-UI using typescript in order to pass additional props to its children. import { NavLink } from 'react-router-dom'; import { Button } from 'material-ui'; <Button ...

The Microsoft Bing Maps V8 TypeScript library is unable to load: "Microsoft is not recognized."

I'm looking to integrate BingMaps into my React project using TypeScript. After installing the npm bingmaps package, I have included the necessary d.ts file. To import the module, I use the following code: import 'bingmaps'; Within my Com ...

Dynamic autocomplete in Oclif utilizing an HTTP request

Is it feasible for Oclif to support the functionality of making API calls to retrieve values for autocomplete? Consider this scenario: A database stores multiple users information Upon typing show users <Tab> <Tab>, the CLI triggers an API ca ...

Error: Trying to access a property of an undefined variable (retrieving 'x')

As a newcomer to the MEAN stack, I am attempting to create some basic posts. However, I keep encountering an error that reads TypeError: Cannot read properties of undefined (reading 'title') when trying to issue a post. The strange thing is, when ...

Tips for simulating difficult private attributes within a class during unit testing in TypeScript

Is there a way to mock the value of a hard private property in a unit test? For example, how can I expect something like expect(event.getEventHis()).toBeEqual(['a', 'b']) export class EventController { #event: []; constructor() { ...

Angular 10: How to Retrieve NgForm from Projected Content

Imagine I have a component structured like this: <app-my-typical-form> <app-child-in-content></app-child-in-content> </app-my-typical-form> where the code for my-typical-form.component.html is as follows: <form #f="ngForm"&g ...

The Angular 6 component adapts to different routes, but encountered an issue: the selector "app-navbar" could not find a matching element

My angular application consists of two separate parts: One for regular users, which is the current view One dedicated to administrators featuring an admin dashboard I am aiming to incorporate these two different views into my app.component.html file. a ...

Steps for transferring an uploaded .CSV file to a Web service

I'm exploring the process of sending a file uploaded from the UI (angular) to a .NET web service in order for it to parse a CSV file and create a list of objects. My current understanding of the logic flow is: File upload ---> Web Service (parse ...

What is the best way to extract and display data from an API response object in my

{ "_metadata": { "uid": "someuid" }, "reference": [ { "locale": "en-us", ... bunch of similar key:value "close_icon_size" ...

Traversing Abstract Syntax Trees Recursively using TypeScript

Currently in the process of developing a parser that generates an AST and then traversing it through different passes. The simplified AST structure is as follows: type LiteralExpr = { readonly kind: 'literal', readonly value: number, }; type ...

Tips for resolving the issue of loading not appearing on screen in Angular

How can I resolve the problem of the loading animation not appearing? Below is the code snippet: HTML <div *ngIf="tempThermometer | async as temp; else loading"> <ng-container *ngIf="temp.length !== 0; else noItems"> &l ...

What is the reason for a type narrowing check on a class property failing when it is assigned to an aliased variable?

Is there a way to restrict the type of property of a class in an aliased conditional expression? Short: I am trying to perform a type narrowing check within a class method, like this._end === null && this._head === null, but I need to assign the r ...

Simplify TypeScript code by converting null or undefined values to numbers

When working with a product, it's important to keep in mind that it can be undefined or null; furthermore, the price within the product can also be undefined or null. For example: getClasses(key: number): string { let product = this.mo ...

What is causing pre-defined variables to act unexpectedly in Cypress?

Encountering unexpected results while pre-defining element variables and using them later in Cypress 10 with Cucumber. Let's take a look at this login test: Given("I'm logged in as Default user", () => { cy.visit('/ ...

The dynamic text feature in my Angular Material gridlist functions perfectly in CodePen, however, it fails to work when

I have enhanced the Angular material gridlist demo by incorporating static and dynamic texts into the grid tiles. While this modification works flawlessly on Codepen (see my provided link), it does not function properly when deployed on my server. The sta ...

Exploring Angular: distinguishing between sessions on separate tabs

I am currently working on a web application that utilizes Angular for the front end and a Django Rest API for the back-end. In some cases, I need the Django Rest API to be able to distinguish between polling requests using session IDs. After conducting som ...