根据输入值更新 ngif
我正在尝试进行搜索以过滤博客中的帖子
这些帖子是从 ngrx 商店作为可观察的
因此,当用户更改输入的值时,帖子(使用异步管道)将由名为filter-posts的管道更新
如果新数组为空,则应显示一条消息“未找到帖子”
问题是更改输入值后未显示消息
这是代码:
posts.component.html:
<div class="posts">
<!--search-->
<input
[(ngModel)]="searchValue"
class="p-2 rounded border w-100 bg-secondary text-light" type="search"
placeholder="Search..." id="search">
<!--posts-->
<ng-container *ngIf="(posts | async).length > 0; else noPosts">
<div class="post" *ngFor="let post of posts | async | filterPosts:searchValue">
<div class="p-title">
<a (click)="goTo('blog/posts/' + post.id.toString(), post)">{{post.title}}</a>
</div>
<div class="p-image">
<img [src]="post.imageSrc" [alt]="post.title">
</div>
<div class="p-cont">
{{post.content | slice:0:80}}
</div>
<div class="p-category">
<a *ngFor="let category of post.categories" class="p-1 m-1 text-light fw-bold">{{category}}</a>
</div>
<div class="p-date">
{{post.date}}
</div>
<app-author class="p-author d-block" [author]="post.author"></app-author>
</div>
</ng-container>
<ng-template #noPosts>
<div class="bg-danger w-100">No Posts Found</div>
</ng-template>
</div>
posts.component.ts:
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { Router } from '@angular/router';
import { faSearch } from '@fortawesome/free-solid-svg-icons';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { Post } from 'src/app/models/post';
import { User } from 'src/app/models/user';
import { setSelectedPostId } from 'src/app/state/posts/actions';
import { getPosts, PostState } from 'src/app/state/posts/reducer';
import { getUserById } from 'src/app/state/users/reducer';
@Component({
selector: 'app-posts',
templateUrl: './posts.component.html',
styleUrls: ['./posts.component.scss']
})
export class PostsComponent {
constructor(private store: Store<PostState>, private router: Router) { }
search = faSearch;
searchValue: string = '';
goTo(path: string, post: Post) {
this.router.navigate([path]);
this.setSelectedPost(post.id);
}
setSelectedPost(id: string) {
this.store.dispatch(setSelectedPostId({id}));
}
getUser(id: string): Observable<User> {
return this.store.select(getUserById(id));
}
posts: Observable<Post[]> = this.store.select(getPosts);
}
filter-posts.pipe.ts:
import { Pipe, PipeTransform } from '@angular/core';
import { Post } from '../models/post';
@Pipe({
name: 'filterPosts',
pure: false
})
export class FilterPostsPipe implements PipeTransform {
transform(value: Post[], searchValue: string): Post[] {
return value.filter(
(post) =>
post.title.toLowerCase().includes(searchValue.toLowerCase()) ||
post.content.toLowerCase().includes(searchValue.toLowerCase()) ||
post.author.name.toLowerCase().includes(searchValue.toLowerCase()) ||
post.categories.includes(searchValue.toLowerCase())
);
}
}
I'm Trying to do a search to filter posts in a blog
the posts are got from the ngrx store as an observable
so when the user changes the value of the input the posts (with async pipe) will be updated by a pipe called filter-posts
and if the new array is empty a message should appear 'no posts found'
the problem is that the message is not shown after changing the input value
this is the code:
posts.component.html:
<div class="posts">
<!--search-->
<input
[(ngModel)]="searchValue"
class="p-2 rounded border w-100 bg-secondary text-light" type="search"
placeholder="Search..." id="search">
<!--posts-->
<ng-container *ngIf="(posts | async).length > 0; else noPosts">
<div class="post" *ngFor="let post of posts | async | filterPosts:searchValue">
<div class="p-title">
<a (click)="goTo('blog/posts/' + post.id.toString(), post)">{{post.title}}</a>
</div>
<div class="p-image">
<img [src]="post.imageSrc" [alt]="post.title">
</div>
<div class="p-cont">
{{post.content | slice:0:80}}
</div>
<div class="p-category">
<a *ngFor="let category of post.categories" class="p-1 m-1 text-light fw-bold">{{category}}</a>
</div>
<div class="p-date">
{{post.date}}
</div>
<app-author class="p-author d-block" [author]="post.author"></app-author>
</div>
</ng-container>
<ng-template #noPosts>
<div class="bg-danger w-100">No Posts Found</div>
</ng-template>
</div>
posts.component.ts:
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { Router } from '@angular/router';
import { faSearch } from '@fortawesome/free-solid-svg-icons';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { Post } from 'src/app/models/post';
import { User } from 'src/app/models/user';
import { setSelectedPostId } from 'src/app/state/posts/actions';
import { getPosts, PostState } from 'src/app/state/posts/reducer';
import { getUserById } from 'src/app/state/users/reducer';
@Component({
selector: 'app-posts',
templateUrl: './posts.component.html',
styleUrls: ['./posts.component.scss']
})
export class PostsComponent {
constructor(private store: Store<PostState>, private router: Router) { }
search = faSearch;
searchValue: string = '';
goTo(path: string, post: Post) {
this.router.navigate([path]);
this.setSelectedPost(post.id);
}
setSelectedPost(id: string) {
this.store.dispatch(setSelectedPostId({id}));
}
getUser(id: string): Observable<User> {
return this.store.select(getUserById(id));
}
posts: Observable<Post[]> = this.store.select(getPosts);
}
filter-posts.pipe.ts:
import { Pipe, PipeTransform } from '@angular/core';
import { Post } from '../models/post';
@Pipe({
name: 'filterPosts',
pure: false
})
export class FilterPostsPipe implements PipeTransform {
transform(value: Post[], searchValue: string): Post[] {
return value.filter(
(post) =>
post.title.toLowerCase().includes(searchValue.toLowerCase()) ||
post.content.toLowerCase().includes(searchValue.toLowerCase()) ||
post.author.name.toLowerCase().includes(searchValue.toLowerCase()) ||
post.categories.includes(searchValue.toLowerCase())
);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
使用
管道
进行此类操作最初似乎是一个好主意,但是当您依赖将在每个更改检测周期运行的不纯管道时,应用程序的性能可能会受到影响。有更简单的方法可以根据另一个值过滤可观察值,我的建议是将搜索输入中的值也视为流。
如果我们不使用
[(ngModel)]
,而是使用FormControl
来监听输入的valueChanges
可观察值,我们可以将流和根据search
值过滤posts
值。你会得到这样的结果
并在你的模板中连接表单控件
这样,就不需要管道,并且当可观察值发生变化时视图应该更新。
The use of a
pipe
for this kind of operation may seem like a good idea initially, but when you rely on an impure pipe that will run on each change detection cycle, the performance of an app can be compromised.There are more simple ways to filter an observable value based on another value, and my suggestion is to consider the values from the search input as a stream aswell.
If we instead of using
[(ngModel)]
use aFormControl
to listen to thevalueChanges
observable of the input, we can combine the streams and filter theposts
value based on thesearch
value.You would en up with something like this
And in your template connect the formcontrol
With this, there is no need for a pipe and the view should update when the observable values change.