Как заставить ng-bootstrap typeahead показывать выпадающие результаты со ссылкой

Я не могу получить результаты из моей службы песен, чтобы показать их в моих результатах ng-bootstrap typeahead. Я получаю сообщение об ошибке: «Невозможно найти другой поддерживающий объект '[объект Object]' типа 'object'. NgFor поддерживает привязку только к Iterables, таким как массивы».

Я пробовал следовать примеру википедии на сайте ng-bootstrap: https://ng-bootstrap.github.io/#/components/typeahead/examples#http

В моем файле .ts есть:

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

  searchSongTitles = (text$: Observable<string>) =>
text$.pipe(
  debounceTime(800),
  distinctUntilChanged(),
  tap(() => this.loadingNavbarSearchSongs$ = true),
  switchMap(term =>
    this.songsService.getSongsQuickSearch(term, this.titleMatchType$, this.sort$, this.sortDirection$).pipe(
      tap(() => this.loadingNavbarSearchSongsFailed$ = false),
      catchError(() => {
        this.loadingNavbarSearchSongsFailed$ = true;
        return of([]);
      })
    )
  ),
  tap(() => this.loadingNavbarSearchSongs$ = false)
)

и мой файл .html имеет:

<input id="songtitles-search" placeholder="Song Title" type="text" 
class="form-control form-control-sm my-sm-0 mr-sm-2" 
name="song_titles_search" [(ngModel)]="songTitlesSearchText$" 
[ngbTypeahead]="searchSongTitles" [resultFormatter]="formatter" 
[inputFormatter]="formatter">

Модель: songsService.getSongsQuickSearch возвращает Observable<Song[]>, где Song имеет следующие свойства: id: number; название: строка;

Мне нужно взять массив песен, поступающих из метода getSongsQuickSearch, чтобы они были интерактивными ссылками на название песни в раскрывающемся списке, которые ссылаются на страницу сведений о песне на основе ее идентификатора. Например:

<a [routerLink]="['/song-details', song.id]">{{ song.title }}</a>


person abovetempo    schedule 10.01.2019    source источник
comment
Не могли бы вы создать его демонстрацию и поделиться ссылкой здесь?   -  person Just code    schedule 10.01.2019
comment
Как я опубликовал, он похож на пример википедии в разделе примеров компонентов typeahead на веб-сайте ng-bootstrap здесь: https://ng-bootstrap.github.io/#/components/typeahead/examples#http Моя проблема очень похожа на эту, но попытка их исправления не сработала: stackoverflow.com/ questions / 52237768 /   -  person abovetempo    schedule 10.01.2019
comment
Можете ли вы опубликовать свой SongsService курс?   -  person Ian A    schedule 14.01.2019


Ответы (2)


Другой способ сделать это - использовать ng-template. Я бы добавил это просто как комментарий, но у меня недостаточно репутации. Надеюсь, это поможет другим, ищущим такое же решение.

https://ng-bootstrap.github.io/#/components/typeahead/examples#template

person Michael    schedule 13.12.2019

В итоге я использовал ng-bootstrap typeahead с настраиваемым представлением ответа. Используется Angular "^ 7.0.1" с "bootstrap": "^ 4.1.3" и @ ng-bootstrap / ng-bootstrap ":" ^ 3.3.1 "

Вот пользовательский CSS, который я использовал для отображения результатов поиска под полем поиска:

#search-results {
    position: absolute;
    width: 160px; /*How wide the results are*/
    background: white;
    border-bottom-left-radius: 10px;
    border-bottom-right-radius: 10px;
    max-height: 500px; /* How far down the results will show */
    overflow-y: auto; /* Show scrollbar if results overflow vertically */
    overflow-x: none; /* Do not show scrollbar horizontally if results overflow */
    border: 1px solid gray;
    left: 150px; /*Where from the left side of the screen the results container starts*/
    right: 0;
    top: 44px; /*Make the results container show under search input*/
}

Вот вид поиска:

<form class="form-inline">
    <input id="songtitles-search" placeholder="Song Title" type="text" class="navbar- 
    search form-control form-control-sm my-sm-0 mr-sm-2" name="song_titles_search" 
    [(ngModel)]="songTitlesSearchText$" [ngbTypeahead]="searchSongTitles">
    <ul id="search-results" class="list-group">
        <li *ngIf="loadingNavbarSearchSongs$" class="list-group-item">
            <img class="small-image" style="width:8em; height:8em;" 
            src="assets/img/loading.gif" />
        </li>
        <li *ngFor="let song of songs$" class="list-group-item">
            <a (click)="songSearchResultChosen()" [routerLink]="['/song-details', 
            song.id]">{{ song.title }}</a> - {{song.main_main_artist}}
        </li>
        <li *ngIf="showNoSearchResultsMessage$">
            <strong>No Song(s) Found Matching Search Criteria</strong>
        </li>
    </ul>
    <button class="btn btn-primary btn-sm my-2 my-sm-0 mr-sm-2" type="submit">
        Search
    </button>
</form>

Вот начальный код машинописного текста:

searchSongTitles = (text$: Observable<string>) =>
text$.pipe(
  debounceTime(800),
  distinctUntilChanged(),
  map(term => {
    this.songs$ = [];
    this.showNoSearchResultsMessage$ = false;
    if (term.length > 0) {
      this.songTitlesSearchText$ = term;
      this.getSongs();
    } else {
      this.loadingNavbarSearchSongs$ = false;
    }
  }
  )
)

Вот метод getSongs, который вызывает настроенную мной службу

getSongs() {
  this.loadingNavbarSearchSongs$ = true;

  this.songsService.getSongsQuickSearch(this.songTitlesSearchText$, this.titleMatchType$,
    this.sort$, this.sortDirection$).subscribe(
    response => {
      this.songs$ = response.songs;
      this.loadingNavbarSearchSongs$ = false;
      if (this.songs$.length <= 0) {
        this.showNoSearchResultsMessage$ = true;
      }
    }
  );
}

Вы можете увидеть рабочий пример на панели навигации на моем веб-сайте abovetempo.com. Надеюсь, это поможет кому-то еще, кто ищет это решение!

person abovetempo    schedule 18.01.2019