Angular 2+ - 检查 Pipe 是不是返回原始列表的空子集
Posted
技术标签:
【中文标题】Angular 2+ - 检查 Pipe 是不是返回原始列表的空子集【英文标题】:Angular 2+ - check if Pipe returns an empty subset of original listAngular 2+ - 检查 Pipe 是否返回原始列表的空子集 【发布时间】:2016-09-01 05:13:32 【问题描述】:我有一个要遍历的字符串列表,但我希望能够使用搜索词过滤它们。像这样:
<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>
【讨论】:
太棒了!我认为第二种解决方案是最好的,因为在第一种解决方案中,您必须遍历列表两次,对吧? 没有更好的办法吗? @ValdemarEdvardSandalRolfsen 那么在第二个解决方案中,如果 item
对象上有多个字段会发生什么?比如, item.name
、 item.age
等等?
@Rexford 我不明白这与问题或我的答案有什么关系,或者问题可能是什么。
谢谢!它节省了我很多时间。 :-)【参考方案2】:
可以利用依赖注入到管道中。你可以注入组件:
然后你可以在它上面设置一个属性来通知这个:
@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;
主要缺点是您在组件内链接管道。优点是过滤执行一次。
【讨论】:
【参考方案3】:这是我从@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 ];
【讨论】:
【参考方案4】:实现此目的的另一种方法是检查 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>
【讨论】:
如果 #element 不是表格(例如 div),则使用 element.children.length 这比复制过滤器代码或返回任意值要好得多,因为接受的答案表明 不再起作用 - 给出ExpressionChangedAfterItHasBeenCheckedError
错误 - 至少在 Angular 4.4.5 上【参考方案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>
【讨论】:
【参考方案6】:这是我能生产的最干净的解决方案。
@Pipe(
name: 'search'
)
export class SearchPipe
transform(value, searchTerm)
let result = ...
if(result.length === 0)
return [undefined];
return result;
通过返回[undefined]
,DOM 中的检查更加简洁易读。
<ng-container *ngFor="let item of list | search: searchTerm">
<div *ngIf="!item">"No matches"</div>
<div *ngIf="item"> item </div>
</ng-container>
【讨论】:
【参考方案7】:Angular 现在支持带有变量的 ngIf,您可以将管道结果分配给一个新变量,然后在 if 块内进行循环
<ng-container *ngIf="search: searchTerm as results; else noItems">
<!-- else is for cases where search:Search term is undefined or null -->
<div *ngFor="let item of results">item</div>
<!-- the case where the pipe returns an empty array -->
<div *ngIf="!result.length">no items match the search</div>
</ng-container>
<ng-template #noItems>searching...</ng-template>
【讨论】:
最干净的解决方案恕我直言以上是关于Angular 2+ - 检查 Pipe 是不是返回原始列表的空子集的主要内容,如果未能解决你的问题,请参考以下文章
Angular 2. *ngFor 的问题,当我使用 Pipe 时