Search code examples
angularangular-services

Displaying no results found when the api returns an empty result set in Angular?


I have developed a search results api which gives the results in an array format. When there are no matching results it results in an empty arry.

I am using Angular to show the results. I want to display the results when the length of the array is greater than zero and display message "No results found" when the length of the array is zero.

But even when there are matching result for the query, it is always showing the length of the array as zero so it is always showing "no results found". I think this is the problem with asynchronous nature. Any help is appreciated.

Html Code:

          <div class="col-sm-12">
            <div *ngIf="carsAvailable; then showCars; else showError"></div>
            <ng-template #showCars>
              <div class="card mb-3" *ngFor="let car of cars">
                <div class="row no-gutters">
                  <div class="col m-3">
                    <div class="w-25 float-left mr-5">
                      <img src="{{car.image1}}" class="img-fluid rounded" alt="">
                    </div>
                    <div class="card-block px-2">
                      <h4 class="card-title">{{car.vehicletitle}}</h4>
                      <p class="card-text">{{car.vehicleoverview | slice:0:200}}</p>
                      <a href="#" class="btn btn-primary">Full Details</a>
                    </div>
                  </div>
                </div>
              </div>
            </ng-template>
            <ng-template #showError>
              <div> No cars found with your search criteria. Please change the search criteria.</div>
            </ng-template>
          </div>

ts code:

import { Component, OnInit } from '@angular/core';
import { CarsdetailsService } from '../services/carsdetails.service';
import { ActivatedRoute } from '@angular/router';

@Component({
  selector: 'app-search',
  templateUrl: './search.component.html',
  styleUrls: ['./search.component.css']
})
export class SearchComponent implements OnInit {

  public cars:any = [];
  public carsAvailable: boolean = false;
  public cityid:string;
  public branchid:string;
  public brandid:string;
  public keywords:string;

  constructor(private _carsdetailsService:CarsdetailsService, private route: ActivatedRoute) { }

  ngOnInit() {
    this.route.queryParamMap.subscribe(queryParams => {
      this.cityid = queryParams.get("city");
      this.branchid = queryParams.get("branch");    
      this.brandid = queryParams.get("brand");    
      this.keywords = queryParams.get("keywords");   
    });
    this._carsdetailsService.getSearchedCars(this.cityid, this.branchid,this.brandid,this.keywords).subscribe(data => this.cars = data.carInfo.cars);
    if(this.cars.length>0){
      this.carsAvailable = true;
    }
    alert(this.carsAvailable);
  }

}

Thanks in advance, Subbu.


Solution

  • You're right it looks like an asynchronous problem. You start your subscription but don't wait for the answer before you check for the.cars.length.

    You just need to move that if statement within the subscription so that it doesn't fire before you get any results:

    this._carsdetailsService.getSearchedCars(this.cityid, this.branchid,this.brandid,this.keywords).subscribe(data => {
        if (data.carInfo.cars.length > 0) {
            this.cars = data.carInfo.cars;
            this.carsAvailable = true;
         }
    

    });

    Also, it'd be more efficient to just set your if statement to check the length of this.cars instead of setting the variable this.carsAvailable:

    <div class="col-sm-12">
        <div *ngIf="this.cars.length > 0; else showError" class="col-sm-12">
              <div class="card mb-3" *ngFor="let car of cars">
                <div class="row no-gutters">
                  <div class="col m-3">
                    <div class="w-25 float-left mr-5">
                      <img src="{{car.image1}}" class="img-fluid rounded" alt="">
                    </div>
                    <div class="card-block px-2">
                      <h4 class="card-title">{{car.vehicletitle}}</h4>
                      <p class="card-text">{{car.vehicleoverview | slice:0:200}}</p>
                      <a href="#" class="btn btn-primary">Full Details</a>
                    </div>
                  </div>
                </div>
              </div>
            </div>
            <ng-template #showError>
              <div> No cars found with your search criteria. Please change the search criteria.</div>
            </ng-template>
          </div>