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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.