简体   繁体   中英

Angular: search filter rxjs

I implement a function that it looks for in the input button by name But I have a problem I made a condition there that I want the input to be empty at the moment so it will get false and display all my data.

Right now as soon as the INPUT is empty I wrote a message "not found": 在此处输入图像描述

What I want it to be is that as soon as the input is empty it will show me all the data and if it is not empty then it will show me the appropriate data or if it does not exist then it will not be found: 在此处输入图像描述

My interface:

export interface Post{
    id:number,
    date: Date,
    authorName:string,
    content:string;
}

My seedDate:

  createDb() {
    const posts: Post[] = [
      {id:1,authorName:"Daniel",content:"Amazon’s Garage Delivery Service"
      ,date:new Date('11/12/20')
    },
      {id:2,authorName:"Omer",content:"Jake From State Farm "
      ,date:new Date('12/20/21')},
      {id:3,authorName:"Lior",content:"The General"
      ,date:new Date('02/01/22')},
      {id:4,authorName:"Tomer",content:"Spotify’s Wrapped "
      ,date:new Date('11/11/20')},
    ];
    return {posts};

html:

<input
  type="search"
  (input)="SearchPostsByName($event)"
  [(ngModel)]="authorName"
/>
<div *ngFor="let post of validPosts">
  <ng-container *ngIf="isExists">
    The name of the author is <b>{{ post?.authorName }}</b> with content
    <b>{{ post?.content }}</b> and released it on the date
    <b>{{ post?.date }}</b>
  </ng-container>
</div>
<br>

typescript:

posts: Post[] = [];
   authorName = "";
   content = "";
   date = new Date();
   isExists = false;
   validPosts: Post[] = [];
   Search:string=''; 

  constructor(private postService: PostService) { }

  ngOnInit(): void {
    this.postService.getPosts().subscribe((posts)=> {
      this.posts = posts;
    });
  }
  
  SearchPostsByName($event : Event) {
    console.log($event);
    if (this.authorName) {
      this.validPosts = this.posts.filter((value) => value.authorName === this.authorName!); 
      if (this.validPosts.length > 0
      ) {
        console.log('found');
        this.isExists = true;
      } else {
        this.isExists = false;
      }
    }
  }

My service:

export class PostService {

  private postsUrl = 'api/posts';

  constructor(private http: HttpClient) { }

  getPosts(): Observable<Post[]> {
    return this.http.get<Post[]>(this.postsUrl);
  }

  addPost(post: Post): Observable<Post> {
    let httpOptions = {
      headers: new HttpHeaders({'Content-Type':'application/json'})
    };
    
    return this.http.post<Post>(this.postsUrl, post, httpOptions)
  }

I believe the biggest mistake is that you forgot to initialize your validPosts inside ngOnInit , which explains why you're not seeing any posts in the beginning:

  ngOnInit(): void {
    this.postService.getPosts().subscribe((posts) => {
      this.posts = posts;
      this.validPosts = posts;
    });
  }

If you want to display all the posts on an empty search, you can check if the search key word is an empty string, if so set your validPosts to posts :

    const searchKey = ($event.target as HTMLInputElement).value;

    if (searchKey === '') {
      this.validPosts = this.posts;
      return;
    }

That's should be it!

Here are some other suggestions that I have if you want to improve this even further:

  1. You do not need to use two way data binding for a simple search like this, simply filtering the posts by the search keyword would be perfectly fine.
  2. You don't have to create the isExists variable just to track if you have any validPosts , since it's an array, you can check its length instead.
  3. You can create a template to display the empty post html
  SearchPostsByName($event: Event) {
    const searchKey = ($event.target as HTMLInputElement).value;

    if (searchKey === '') {
      this.validPosts = this.posts;
      return;
    }

    this.validPosts = this.posts.filter(
      (value) => value.authorName === searchKey
    );
  }
<input type="search" (input)="SearchPostsByName($event)" />
<ng-container *ngIf="validPosts.length; else emptyPostTpl">
  <div *ngFor="let post of validPosts">
    The name of the author is <b>{{ post?.authorName }}</b> with content
    <b>{{ post?.content }}</b> and released it on the date
    <b>{{ post?.date }}</b>
  </div>
</ng-container>
<br />

<ng-template #emptyPostTpl>
  <span style="font-size: 1rem; font-weight: bold; display: block"
    >No post found</span
  >
</ng-template>

Want to take it even further?

  1. Take a look at onPush change detection to improve performance.
  2. Learn RXJS and implement a debounce search!

I suggest you to replace your input event , with keyup .

 <input type="search" (keyup)="SearchPostsByName($event)" [(ngModel)]="authorName" />

In SearchPostsByName($event), query event$.target.value to check if there's any input:

 SearchPostsByName($event : Event) { if(!$event.target.value.length) { return; } if (this.authorName) { this.validPosts = this.posts.filter((value) => value.authorName === this.authorName!); if (this.validPosts.length > 0 ) { console.log('found'); this.isExists = true; } else { this.isExists = false; } }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM