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

3
  • are you getting correct data in this.stars = this.commentList.map(x => x.Rate); Commented Mar 12, 2019 at 10:20
  • Possible duplicate of Can I repeat *ngFor an arbitrary number of times using built in angular directives? Commented Mar 12, 2019 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. Commented Mar 12, 2019 at 10:25

3 Answers 3

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

4 Comments

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.
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 I don't think you have understood the question. He wants just to display x number of stars.
hmm indeed, looks like I extrapolated. +1 for promoting pipe ! I'm a bit sad you don't return an iterator :p
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

Comments

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>

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.