Show autocomplete list on keypress in a input field

Viewed 692

I have a list of friends which is an array. I have a input field. if i press any letter after @ in that input field, how can i get suggestions of friends from my friends array. Something like Facebook comment box. If i press any letter after @ it immediately shows filtered friends name's with that particular letter.

Question how I can show friends list on any key press after @

<input type="text" id="friendInput" (keypress)="onSearchFriend($event)">
<div class="autocompleteFriendList" *ngIf="filteredFriends.length > 0">
  <ul>
    <li *ngFor="let friend of filteredFriends">
      {{ friend.name }}
    </li>
  </ul>
</div>


filteredFriends : any = [];
friends : Array<any> = [
    {id: 1, name: 'Bob'},
    {id: 2, name: 'max'},
    {id: 3, name: 'Charlie'},
    {id: 4, name: 'jhon'},
    {id: 5, name: 'Tom'}
]


onSearchFriend(event : any){
  let inputEl : any = document.getElementById(friendInput);
  if(event.key == '@'){
      
  }
}
2 Answers

Below Works using Observables

In your TS file

import { combineLatest, Subject, of } from 'rxjs';
import { map } from 'rxjs/operators';

searchValue;
friends : Array<any> = [
    {id: 1, name: 'Bob'},
    {id: 2, name: 'max'},
    {id: 3, name: 'Charlie'},
    {id: 4, name: 'jhon'},
    {id: 5, name: 'Tom'}
]

filterString$ = new Subject<string>()

filteredFriends$ = combineLatest([this.filterString$, of(this.friends)]).pipe(
    map(([filterString, friends]) => 
      filterString === '' ? '' : 
      friends.filter(() => filterString != '@')
             .filter(({name}: {name: string}) => 
        ((new RegExp('@[a-zA-Z]*' + filterString.toLowerCase().substring(1) +'[a-zA-Z]*')).test('@' + name.toLowerCase()))
      )
    )
  )

And In your HTML

<input type="text" id="friendInput" [(ngModel)]="searchValue" 
 (ngModelChange)="filterString$.next(searchValue)">
<div class="autocompleteFriendList" *ngIf="filteredFriends$ | async as filteredFriends">
  <ul>
    <li *ngFor="let friend of filteredFriends">@{{ friend.name }}</li>
  </ul>
</div>

Stackblitz Demo

Here is the updated code with some tweaks. Component

export class AppComponent  {
searchValue;
filteredFriends : any = [];
friends : Array<any> = [
    {id: 1, name: 'Bob'},
    {id: 2, name: 'max'},
    {id: 3, name: 'Charlie'},
    {id: 4, name: 'jhon'},
    {id: 5, name: 'Tom'}
]


onSearchFriend(event : any){
  
  if(this.searchValue && this.searchValue[0]==='@'){
  
  const searchKey = this.searchValue.replace('@','');
  console.log(event.key, searchKey);
   this.filteredFriends = this.friends.filter(item=>item.name.startsWith(searchKey))    
  }
}
}

HTML template

<input type="text" id="friendInput" 
[(ngModel)]="searchValue" 
(keyup)="onSearchFriend($event)">
<div class="autocompleteFriendList" *ngIf="filteredFriends.length > 0">
  <ul>
    <li *ngFor="let friend of filteredFriends">
      {{ friend.name }}
    </li>
  </ul>
</div>

https://stackblitz.com/edit/angular-ivy-haniuh?file=src/app/app.component.html

Related