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)
}
CodePudding user response:
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:
- 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. - You don't have to create the
isExists
variable just to track if you have anyvalidPosts
, since it's an array, you can check its length instead. - 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?
- Take a look at
onPush
change detection to improve performance. - Learn RXJS and implement a debounce search!
CodePudding user response:
For what i can see, when your input is empty, your searchPostsByName
method is not doing anything, if you add the not empty condition and return all posts you'd get a list of all posts when no filter is present:
SearchPostsByName($event : Event) {
if (!this.authorName) { // if empty, return all posts
this.isExists = true;
return this.posts;
}
if (this.authorName) { // if not empty, filter
this.validPosts = this.posts.filter((value) => value.authorName === this.authorName!);
if (this.validPosts.length > 0
) {
this.isExists = true;
} else {
this.isExists = false;
}
}
CodePudding user response:
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;
}
}