Search code examples
javascriptangularangular-ng-if

Angular 8 => Condition : show an else value


I'm trying to filter a default value if no result is found on my query.

I tried using ng-template, but I simply don't manage to do it.


Rather than writing, here are images to better understand :

enter image description here

enter image description here

This is my successful filter : it correctly shows my datas once I filter them in the search box.


However if I try to enter an invalid data as done below :

enter image description here

It simply returns me an empty html table.

Which is not what I'd like to achieve. I'd like it instead to show a message saying : no data found.

How can I do it please?


And here is my source code :

Component :

import {Component, OnInit} from '@angular/core';
import {IProduct} from './product';

@Component({
  selector: 'pm-products',
  templateUrl: './product-list.component.html',
  styleUrls: ['./product-list.component.css']
})

export class ProductListComponent implements OnInit {

  ///////////////////////////////////// PROPERTIES //////////////////////////////////////

  // String Interpolation
  pageTitle = 'Product List';

  // Property binding
  imageWidth = 50;
  imageMargin = 2;

  // Event binding
  showImage = false;

  // Two-way binding
  // listFilter = 'cart';

  // Filter products
  private _listFilter: string;

  // Filter Products Array
  filteredProducts: IProduct[];

  ///////////////////////////////////// CONSTRUCTOR //////////////////////////////////////

  constructor() {
    this.filteredProducts = this.products;
    this.listFilter = 'cart';
  }

  /////////////////////////////////// GETTERS/SETTERS ///////////////////////////////////

  get listFilter(): string {
    return this._listFilter;
  }

  set listFilter(value: string) {
    this._listFilter = value;
    /***
     * If there is a list of filtered value, show the list of the filtered values => this.performFilter(this.listFilter)
     * Else, (if there is no filtered) return the whole set of products
     */
    this.filteredProducts = this.listFilter ? this.performFilter(this.listFilter) : this.products;
  }

  /////////////////////////////////////// METHODS ///////////////////////////////////////

  // Get Products
  products: IProduct[] = [
    {
      productId: 2,
      productName: 'Garden Cart',
      productCode: 'GDN-0023',
      releaseDate: 'March 18, 2019',
      description: '15 gallon capacity rolling garden cart',
      price: 32.99,
      starRating: 4.2,
      imageUrl: 'assets/images/garden_cart.png'
    },
    {
      productId: 5,
      productName: 'Hammer',
      productCode: 'TBX-0048',
      releaseDate: 'May 21, 2019',
      description: 'Curved claw steel hammer',
      price: 8.9,
      starRating: 4.8,
      imageUrl: 'assets/images/hammer.png'
    },
  ];

  performFilter(filterBy: string): IProduct[] {
    /**
     * filterBy result => to lower case. => case insensitive comparison.
     * Return a new array of the filtered productS by the product name,
     * by checking if that product name given is an index of the an element in the product array.
     */
    filterBy = filterBy.toLowerCase(); // 1.
    return  this.products.filter((product: IProduct) => product.productName.toLowerCase().indexOf(filterBy) !== - 1); // 2.
  }

  toggleImage = (): void => {
    this.showImage = !this.showImage;
  }

  ////////////////////////////////// LIFECYCLE HOOKS ///////////////////////////////////

  ngOnInit(): void {
    console.log('hello');
  }
}

HTML

<div class="card">

  <div class="card-header">{{pageTitle}}</div>

  <!-- CARD -->
  <div class="card-body">
    <div class="row">
      <div class="col-md-2"> Filter by:</div>
      <div class="col-md-4">
        <input [(ngModel)]="listFilter" type="text"/>
      </div>
    </div>
    <div class="row">
      <div class="col-md-6">
        <h4>Filtered by: {{listFilter}} </h4>
      </div>
    </div>
    <!-- ./CARD -->

    <!-- TABLE -->
    <div class="table-responsive">
      <table *ngIf="products && products.length" class="table">
        <thead>
        <tr>
          <th>
            <button (click)="toggleImage()" class="btn btn-primary">{{showImage ? "Hide" : "Show"}} image</button>
          </th>
          <th>Product</th>
          <th>Code</th>
          <th>Available</th>
          <th>Price</th>
          <th>5 Star Rating</th>
        </tr>
        </thead>
        <tbody>
        <tr *ngFor="let product of filteredProducts">
          <td><img *ngIf="showImage" [src]="product.imageUrl" [title]="product.productName"
                   [style.width.px]="imageWidth" [style.margin.px]="imageMargin" alt=""></td>
          <td>{{product.productName}}</td>
          <td>{{product.productCode | lowercase | convertToSpaces: '-'}}</td>
          <td>{{product.releaseDate}}</td>
          <td>{{product.price | currency: 'EUR':'symbol':'2.2-2'}}</td>
          <td>{{product.starRating}}</td>
        </tr>
        </tbody>
      </table>
    </div>
    <!-- ./TABLE -->
  </div>
</div>

Please take care of yourself.


Solution

  • Maybe just include an *ngIf="!filteredProducts.length" wherever you'd like to show your message.

    ex.

    
    <tr *ngFor="let product of filteredProducts">
        //Your table stuff
    </tr>
    <tr *ngIf="!filteredProducts.length">
         <td colspan="6">No data found</td>
    </tr>