Angular 2+ - проверьте, возвращает ли Pipe пустое подмножество исходного списка

У меня есть список строк, которые я хочу перебрать, но я хочу, чтобы их можно было фильтровать с помощью поискового запроса. Вот так:

<div *ngFor="#item in list | search: searchTerm">{{ item }}</div>

Мой вопрос:, как я могу проверить, возвращает ли пул пустое подмножество списка?

Другими словами, если ни одна из строк не соответствует поисковому запросу, я хочу отобразить сообщение с сообщением "Нет совпадений".

Ответ 1

<div *ngIf="(list | search: searchTerm).length === 0">
  "No matches"
</div>
<div *ngFor="#item in list | search: searchTerm">{{ item }}</div>

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

@Pipe({
  name: 'search'
})
export class SearchPipe {

  transform(value, searchTerm) {
    let result = ...
    if(result.length === 0) {
      return [-1];
    }
    return result;
  }
}
<ng-container *ngFor="let item of list | search: searchTerm">
  <div *ngIf="item === -1">"No matches"</div>
  <div *ngIf="item !== -1">{{ item }}</div>
</ng-container>

Ответ 2

Еще один способ добиться этого - проверить элемент html для детей или в моем случае таблицу для строк.

<table #myTable>
  <tr *ngFor="let item of list | somePipe : searchText">
      <td>{{ item.name }}</td>
  </tr>
</table>

<p *ngIf="!myTable.rows.length">No results</p>

Ответ 3

Можно использовать вливание зависимостей в трубы. Вы можете ввести компонент:

Затем вы можете установить для него свойство, чтобы уведомить об этом:

@Pipe({
  name: 'search'
})
export class SearchPipe {
  constructor(@Inject(forwardRef(() => SomeComponent)) private comp:SomeComponent) {

  }

  transform(value) {
    var filtered = value.map((v) => v-1);
    this.comp.isEmpty = (filtered.length === 0);
    return filtered;
  }
}

Основной недостаток заключается в том, что вы связываете трубку внутри компонента. Преимущество состоит в том, что фильтрация выполняется один раз.

Ответ 4

Это мой код, который немного изменился с @Günter Zöchbauer

<div  *ngFor="let filter_list of list | FilterItem" >
    <div *ngIf=" filter_list == -1 " class="alert alert-info">No item found</div>    
    <div *ngIf="filter_list !== -1" *ngFor="let item of filter_list  ; let i = index;" >
        {{ item }}
    </div>
</div>

Код трубы

@Pipe({
  name: 'FilterItem'
})
export class FilterItem {

  transform(list, args?) {
       let result = ...; 
       if ( result && result.length > 0 ){
          return [ result ];
       }else{
          return [ -1 ];
       }
  }
}

Ответ 5

Если ваша цель - просто визуализировать элемент, чем вы могли бы сделать с помощью CSS-запроса, я просто подменяю код Günter Zöchbauer.

<ng-container *ngFor="let item of list | search: searchTerm">
  <div *ngIf="item !== -1">{{ item }}</div>
  <div class="empty">"No matches"</div>
</ng-container>

CSS

div.empty {
  display:none;
}
div.empty:first-child {
  display:block;
}

.list div.empty {
  display: none;
}

.list div.empty:first-child {
  display: block;
}
<h4>If you hava record to display than</h4>
<div class="list">
  <div>The first record.</div>
  <div>The second record.</div>
  <div>The third record.</div>
  <div class="empty">"No matches"</div>
</div>
<br>
<h4>If no record to show</h4>
<div class="list">
  <div class="empty">"No matches"</div>
</div>