Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ng-bootstrap typeahead: how to handle Observable<Person[]> rather than Observable<string[]>

I've a newbie Angular/Typescript question.

I followed the Wikipedia example defined in ng-bootstrap typeahead and I decided to replace the Wikipedia call with a custom REST service that provides the following GET call:

  • GET /person/name/{name}

and returns a list of persons matching the name, where each person is:

Person(id:long, name:string, surname:string)

Now from the typescript part and the angular part everything works fine if I map(...) the array of persons to an array of string of names into the _service:

  • [p1, p2, p3] -> [nameP1, nameP2, ...]

But I'd like to don't map that way in the _service and returns the list of persons to allow the user to click on the result in the dropdown and then display the detail of the person without subsequent calls.

So at the moment in my typescript component, the model is:

model: Observable<Person[]>;

And the search part is the following:

search = (text$: Observable<string>) =>
        text$.pipe(
            debounceTime(300),
            distinctUntilChanged(),
            tap(() => this.searching = true),
            switchMap(term =>
                this._service.search(term).pipe(
                    tap(() => this.searchFailed = false),
                    catchError(e => {
                        this.searchFailed = true;
                        return of([]);
                    }))
            ),
            tap(() => this.searching = false),
            merge(this.hideSearchingWhenUnsubscribed)
        )

while the html part is:

 <div class="input-group input-group-lg" id="person-search">
        <input name="name" id="typeahead-http" type="text" class="form-control" [class.is-invalid]="searchFailed" (selectItem)="selectedItem($event)" [(ngModel)]="model" [ngbTypeahead]="search" placeholder="Search a person"/>
        <span class="input-group-btn">
            <button class="btn btn-primary btn-lg" type="button">
              <i class="text-muted fa fa-search"></i>
            </button>
        </span>
  <div>

How can I show just the names in the dropdown and allow the user to click on the name and show him the corresponding person?

like image 942
Momo Avatar asked Oct 16 '22 13:10

Momo


1 Answers

You need a resultFormatter which will show the name, but you also need inputFormatter to show just the name when you choose a value, otherwise it will show [object Object] in the input field. These both are provided by the typeahead.

So in your ts, mark that you want to show the name in both results and in input:

formatter = (x: { name: string }) => x.name;

and you will use these in template like so:

<input ... [resultFormatter]="formatter" [inputFormatter]="formatter"/>

Your model will still contain the whole object.

like image 173
AT82 Avatar answered Nov 03 '22 00:11

AT82