1

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.

3 Answers 3

4

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>
Sign up to request clarification or add additional context in comments.

2 Comments

Oh that was that simple !! Sorry I'm new to Angular. Thank you very much. Need to wait a little before validating your answer.
@Finalmix6 No worries. Glad it helped!
2

You have to add tr contains string no data found after ngfor tr

  <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>

<tr *ngIf="filteredProducts.length === 0 " >
<td colspan="6" >Your message here </td>
</tr>

Comments

2

You can simply add a row that appears only when the list is empty and the search bar has any value. like this:

 <tr *ngFor="let product of filteredProducts">...</tr>

 <tr col-span ="6" *ngIf="!filteredProducts.length && listFilter.length"> uh oh, 
 could not find what you searched for</tr>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.