Search code examples
javascriptangulartypescriptionic-framework

Angular show different divs based on search input and on no input


Hello :) I am making a search in my Angular 14 + Ionic v6 app and have made a search field so the user can search for products. The search is an API call. I have now three scenarios that I'd like to achieve.

  1. The user is on the search page and has not entered any text in the search so there is a div bellow the search input field that shows "Enter atleast 3 characters to search..."

  2. The second one is if the userhas searched for something but there were no results. I want to display a div with text: "Your search did not find any results..."

  3. Show search results -> THIS WORKS

So how do I show the two other divs? They are now both vissible at the same time... What have I done wrong in my code?

HTML markup:

  <ion-searchbar inputmode="search" [debounce]="1000" placeholder="Iskanje" show-clear-button="focus" (change)="search($event)"></ion-searchbar>
  <ion-list>
    <ion-item *ngIf="products.length === 0" class="ion-text-center">
      <ion-label>
        <span class="prod-code">Enter atleast 3 characters to search...</span>
      </ion-label>
    </ion-item>
    <ion-item routerLink="/product/{{produkt.id}}" *ngFor="let produkt of products">
      <ion-label>
        <span class="prod-code">{{ produkt.product_code }}</span>
        <span class="prod-name">{{ produkt.name }}</span>
      </ion-label>
    </ion-item>
    <ion-item *ngIf="products.length === 0" class="ion-text-center">
      <ion-label>
        <span class="prod-code">Your search did not find any results...</span>
      </ion-label>
    </ion-item>
  </ion-list>

TS code for search api call:

import { Component, OnInit } from '@angular/core';
import { SearchService } from '../services/search.service';
import { ToastController } from '@ionic/angular';

@Component({
  selector: 'app-search',
  templateUrl: './search.page.html',
  styleUrls: ['./search.page.scss'],
})
export class SearchPage implements OnInit {
  term: string;
  products: any = [];
  // searchResult: SearchResult;

  constructor(
    private searchService: SearchService,
    private toastController: ToastController,
  ) { }

  ngOnInit() {

  }

  search(event: any) {
    console.log('Searched value = ' + event.target.value);
    const searchTerm = event.target.value;
    if(searchTerm === '') {
      return this.products = [];
    } else {
      this.searchService.searchByTermCall(searchTerm).subscribe(
        (data: any) => {
          console.log(data.body);
          this.products = data.body;
        },
        error => {
          console.log('Error', error);
        }
      );
    }
  }

  async errorToast(message, position: 'bottom') {
    const toast = await this.toastController.create({
      message,
      duration: 3000,
      color: 'danger',
      icon: 'close-circle-outline',
      position
    });
    await toast.present();
  }

}

Solution

  • You can use nested ngIf, if your products array is undefined before first search event, if not you need to change first ngIf logic according to the search bar value.

    <ion-searchbar inputmode="search" [debounce]="1000" placeholder="Iskanje" show-clear-button="focus" (change)="search($event)"></ion-searchbar>
    <ion-list>
       <ion-item *ngIf="!products; else searched" class="ion-text-center">
          <!-- Enter at least 3 characters.. -->
       </ion-item>
       <ng-template #searched>
          <ion-item *ngIf="products.length !== 0; else emptyList" class="ion-text-center">
             <!-- Render products with ngFor.. -->
          </ion-item>
          <ng-template #emptyList>
             <!-- No result.. -->
          </ng-template>
       </ng-template>
    </ion-list>