2

I get the concept of how to get a simple image into the cell like this

<img [src]="element.imageUrl" />

But i am wondering what the best way would be to display a collection of stars. Lets say i have a field called overallRaiting which holds a value of 0 to 5. If the value is 0 i want to show no star , if its 1 then 1 star ,if 2 then 2 stars and so on. Here is what i came up with so far which works but hope there might be better way.

    <ng-container matColumnDef="imageUrl">
    <th mat-header-cell *matHeaderCellDef> Image Url </th>
    <td mat-cell *matCellDef="let element"> 
      <img *ngIf="element.overallRaiting>=1" [src]="element.imageUrl" />
      <img *ngIf="element.overallRaiting>=2" [src]="element.imageUrl" />
      <img *ngIf="element.overallRaiting>=3" [src]="element.imageUrl" />
      <img *ngIf="element.overallRaiting>=4" [src]="element.imageUrl" />
      <img *ngIf="element.overallRaiting>=5" [src]="element.imageUrl" />
  </ng-container>

Would i have to do a *ngif for each nbr or is the a cleaner more reusable way ?

Ok tried this on

          <ng-container matColumnDef="overall_rating">
            <th mat-header-cell *matHeaderCellDef> Overall Rating </th>
            <td mat-cell *matCellDef="let element"> 
                <ng-container *ngFor="let i of [].constructor(element.overall_rating)">
                    <img class="star" src="../../assets/images/basic-5-point-gold-star-beveled.jpg" />
                  </ng-container>
              {{element.overall_rating}}
              </td>
          </ng-container>

Which produces this in doc

 <td _ngcontent-snv-c2="" class="mat-cell cdk-column-overall_rating mat-column-overall_rating" mat-cell="" role="gridcell"><!--bindings={
      "ng-reflect-ng-for-of": "4"
    }--><!----><img _ngcontent-snv-c2="" class="star" src="../../assets/images/basic-5-point-gold-star-beveled.jpg"> 4 </td>

enter image description here

NoSoup4you
  • 640
  • 1
  • 10
  • 34

2 Answers2

4

You can use *ngFor to avoid having multiple *ngIfs.

<ng-container matColumnDef="imageUrl">
    <th mat-header-cell *matHeaderCellDef> Image Url </th>
    <td mat-cell *matCellDef="let element"> 
      <ng-container *ngFor="let i of [].constructor(element.overallRating)">
        <img [src]="element.imageUrl" />
      </ng-container>
    </td>
</ng-container>

There are other ways you can repeat an element using *ngFor, but this looked simpler.

You can also abstract away this logic and create a child component which takes rating as input and displays corresponding number of stars.

<ng-container matColumnDef="imageUrl">
    <th mat-header-cell *matHeaderCellDef> Image Url </th>
    <td mat-cell *matCellDef="let element"> 
      <app-star-rating [rating]="element.overallRating"><app-star-rating>
    </td>
</ng-container>
Nikhil
  • 6,493
  • 10
  • 31
  • 68
  • I tried the *ngFor in your first recomendation but it seems to no do what i expect. In my case element.overallRating is a single number which can be either 0 to 5 – NoSoup4you Sep 16 '19 at 20:41
  • @NoSoup4you - What is it showing on the screen? Are you getting any error? I had corrected the spelling to `Rating`, it was `Raiting` in your question. – Nikhil Sep 16 '19 at 21:00
  • @NoSoup4you - Check out my edited answer. We have to use `*ngFor` on an iterable object, but I was using it on just a number earlier. Fixed it now. – Nikhil Sep 16 '19 at 22:09
  • tried new code but still dont get what i need, i updated my question with the changes and the result – NoSoup4you Sep 16 '19 at 23:12
  • @NoSoup4you - What you have should work. Check out https://stackblitz.com/edit/angular-material-with-angular-v5-ldaaqk where I demonstrated this. Also, please replace the code there with yours and let me know when you are done, I'll take a look. – Nikhil Sep 16 '19 at 23:20
0

Ok based on @Nikhil answer the folowing code works for me now. The issue in my case ended being that the number was in string format which created only a single loop.

 <ng-container matColumnDef="overall_rating">
            <th mat-header-cell *matHeaderCellDef> Overall Rating </th>
            <td mat-cell *matCellDef="let element"> 
                <ng-container *ngFor="let i of [].constructor(NumberConverter(element.overall_rating))">
                    <img class="star" src="../../assets/images/basic-5-point-gold-star-beveled.jpg" />
                  </ng-container>
              </td>
          </ng-container>

then on the controller i added the function

NumberConverter(value: any) {
  if (value === null || value === undefined || typeof value === 'number') {
      return value;
  }

  return parseFloat(value.toString());
}

that made sure it always returned the value in number format if it was posible

NoSoup4you
  • 640
  • 1
  • 10
  • 34