1

I created star rating system. In the Rate property, I keep the rating on a scale of 1 to 5. I assigned the Rate property to an Stars array in which these values are.
I have a problem with correctly displaying values from the table. For example, the rating value is 5 and should display 5 stars and in my case it displays only 3. How to solve it?
enter image description here Component:

 export class RatingStarComponent implements OnInit {

  commentList: Rating[];
  stars: number[];
  constructor(private productService: CategoriesProductsService, private router: Router ) { }

  ngOnInit() {
    this.productService.getComment().subscribe(data => {
      this.commentList = data;
      this.commentList = this.commentList.filter(x => x.ProductId === this.products.Id);
      this.stars = this.commentList.map(x => x.Rate);
      console.log('Comment List:', this.commentList);
      console.log('Stars:', this.stars);
    });
  }

HTML:

 <div class="row" *ngFor="let comment of commentList">
  <div class="col-sm-12">
   Comment: {{comment.Comment}} <br/> 
   Your rating: {{comment.Rate}}
  </div>
  <div class="col-sm-6" >
    <ul class="list-inline ratingList" *ngFor="let x of stars">
      <li >
          <i value="x"  class="fa fa-star fa-lg"></i> 
      </li>
    </ul>
  </div>
</div>

Any help or sugestion is welcome

k_dadun
  • 121
  • 1
  • 1
  • 9
  • are you getting correct data in this.stars = this.commentList.map(x => x.Rate); – Mohit Saxena Mar 12 '19 at 10:20
  • Possible duplicate of [Can I repeat \*ngFor an arbitrary number of times using built in angular directives?](https://stackoverflow.com/questions/40251160/can-i-repeat-ngfor-an-arbitrary-number-of-times-using-built-in-angular-directiv) – Akber Iqbal Mar 12 '19 at 10:23
  • @AkberIqbal this is not a duplicate, at least try to understand the question before flagging... op has a problem with its logic. – Florian Mar 12 '19 at 10:25

3 Answers3

4

It's not 3, it's the length of your comments array. You are iterating over the array of 3 items, it will always be 3 stars if there are 3 comments.

Add stars property to your comments:

this.commentList = this.commentList.map(comment => Object.assign(comment, {stars: new Array(comment.Rate)}));

And iterate separately for every comment:

<ul class="list-inline ratingList" *ngFor="let x of comment.stars">
  <li >
    <i value="x"  class="fa fa-star fa-lg"></i> 
  </li>
</ul>


You could probably make a toArray pipe to return an array from the Rate number and use it like this:

*ngFor="let x of (comment.Rate | toArray)"

That way you won't need to mutate your commentList array like this:

// this.commentList = this.commentList // .map(comment => Object.assign(comment, {stars: new Array(comment.Rate)}));

Pipe will return an array of length from the number (Rate in your example):

import { Pipe, PipeTransform } from '@angular/core';
@Pipe({name: 'toArray'})
export class ToArrayPipe implements PipeTransform {
  transform(value: number): any[] {
    return new Array(value);
  }
}
Roberto Zvjerković
  • 9,657
  • 4
  • 26
  • 47
  • Sure, then they should expose a function to get an array from a number and keep in mind that they should not call functions from template without `OnPush` since they will get triggered on each change detection cycle, or build a pipe to pipe a number to an array. But they are obviously new to angular and this is the easiest way. – Roberto Zvjerković Mar 12 '19 at 10:25
  • it doesn't solve op problem. He wants to display 5 stars and color x of them based on the `comment.Rate`. + building a pipe is indeed a nice and elegant solution, I'd definetly upvote such an answer, however a bit harder to explain to a newcomer... – Florian Mar 12 '19 at 10:30
  • @Florian I don't think you have understood the question. He wants just to display x number of stars. – Roberto Zvjerković Mar 12 '19 at 10:36
  • hmm indeed, looks like I extrapolated. +1 for promoting pipe ! I'm a bit sad you don't return an `iterator` :p – Florian Mar 12 '19 at 10:39
0

Change the value attribute in i like this

<i value="x"  class="fa fa-star fa-lg"></i> 

to

<i [value]="x"  class="fa fa-star fa-lg"></i>

because your x value is dynamic to bind the dynamic value you need to use []brackets

Sheik Althaf
  • 1,595
  • 10
  • 16
0

You need 5 but getting 3 because of your this.stars Array

This is how I handled a similar case in my app. this.starWidth = this.rating * 75 / 5;

html

<div [style.width.px]="starWidth" >
      <div style="width: 75px">
        <span class="fa fa-star"></span>
        <span class="fa fa-star"></span>
        <span class="fa fa-star"></span>
        <span class="fa fa-star"></span>
        <span class="fa fa-star"></span>
      </div>
    </div>

probably, in your case

<div class="row" *ngFor="let comment of commentList">
          <div class="col-sm-12">
           Comment: {{comment.Comment}} <br/> 
           Your rating: {{comment.Rate}}
          </div>
          <div class="col-sm-6" >
            <div [style.width.px]="comment.Rate * 75 / 5 " >
                <div style="width: 75px">
                    <span class="fa fa-star"></span>
                    <span class="fa fa-star"></span>
                    <span class="fa fa-star"></span>
                    <span class="fa fa-star"></span>
                    <span class="fa fa-star"></span>
                </div>
            </div>
          </div>
        </div>
Community
  • 1
  • 1
skdonthi
  • 1,308
  • 1
  • 18
  • 31