1

I'm trying to use angular-star-rating in my angular4 project which was generated with the help of angular CLI. I am using bootstrap-4. I have followed this documentation [URL] https://www.npmjs.com/package/angular-star-rating Steps which I have followed:

  1. npm install angular-star-rating --save
  2. copied the images from ./node_modules/angular-star-rating/assets/images folder into ./src/assets/images.
  3. In style.css, @import "~angular-star-rating/assets/scss/star-rating";
  4. In app.module, import { StarRatingModule } from 'angular-star-rating';
  5. Then In the imports array, specified the library

this is how my folder structure look likenew structure the error which I am getting is related to style.css file, i.e., step-3. probably it is not able to find the scss file which is present inside "~angular-star-rating/assets/scss/star-rating";Error related to path

I have tried to put the absolute path too but that too didn't work either.

Humble Dolt
  • 940
  • 2
  • 16
  • 31

4 Answers4

2

This problem comes from versions incompatibility. Fix both angular-star-rating and css-star-rating in your package.json

"angular-star-rating": "3.0.8",
"css-star-rating": "1.1.3"
Voskanyan David
  • 987
  • 6
  • 6
1

That library seems to be quite out of date and breaks my project as well. I saw your answer because I was looking for a star rating solution as well and so I will share my very simple but working solution with you without using any npm module so you can improve on it on your project. Keep in mind that my solution works with socket.io and observables in the service so you will need to either implement it or easier just remove all references to socket.io and material modules with your own code. Code is quite ugly but it will get you going:

ng-ratings.component.ts

import { Component, OnInit, Input } from '@angular/core';
import { NewsRatingsService } from './news-ratings.service';
import { MdSnackBar, MdSnackBarConfig } from '@angular/material';

@Component({
  selector: 'app-ng-ratings',
  templateUrl: './ng-ratings.component.html',
  styleUrls: ['./ng-ratings.component.css'],
  providers: [MdSnackBar]
})
export class NgRatingsComponent implements OnInit {

  checked_5: boolean;
  checked_45: boolean;
  checked_4: boolean;
  checked_35: boolean;
  checked_3: boolean;
  checked_25: boolean;
  checked_2: boolean;
  checked_15: boolean;
  checked_1: boolean;
  checked_05: boolean;
  checked_0: boolean;

  connection: any;
  messageObjectResponse: any;
  messageObject: any = {};

  @Input('news_id') news_id: any;
  @Input('ratingVal') ratingVal: any;

  constructor(private newsRatingsService: NewsRatingsService, public snackBar: MdSnackBar) { }

  ngOnInit() {
    console.log('in ng-ratings module init');
    console.log(this.ratingVal);
    this.ratingVal = this.ratingVal + 0;
    this.rate(this.ratingVal);

    this.connection = this.newsRatingsService.getMessages().subscribe(message => {
          this.messageObjectResponse = message;
            console.log('receiving message: ');
            console.log(this.messageObjectResponse);
          switch (this.messageObjectResponse.type) {
              case 'rate-news':
                  this.rate(this.messageObjectResponse.ratingVal);
              break;
              case 'error-message':
                this.toast(this.messageObjectResponse.message);
                this.messageObjectResponse = {};
              break;
              case 'sent-rating':
                this.toast(this.messageObjectResponse.message);
                this.messageObjectResponse = {};
              break;

              default:
              break;
              }
              this.ratingVal = this.messageObjectResponse.average;
    });
  }

  rate(rateVal: number) {
      if (rateVal> 0 && rateVal<= 0.5) {
          this.checked_05 = true;
      } else if (rateVal > 0.5 && rateVal<= 1) {
          this.checked_1 = true;
      } else if (rateVal > 1 && rateVal <= 1.5) {
          this.checked_15 = true;
      } else if (rateVal > 1.5 && rateVal <= 2) {
          this.checked_2 = true;
      } else if (rateVal > 2 && rateVal <= 2.5) {
          this.checked_25 = true;
      } else if (rateVal > 2.5 && rateVal <= 3) {
          this.checked_3 = true;
      } else if (rateVal > 3 && rateVal <= 3.5) {
          this.checked_35 = true;
      } else if (this.ratingVal > 3.5 && rateVal <= 4) {
          this.checked_4 = true;
      } else if (rateVal > 4 && rateVal <= 4.5) {
          this.checked_45 = true;
      } else if (rateVal > 4.5) {
          this.checked_5 = true;
      }
  }

  send(event: any) {
    console.log(event);
    this.hackTemplateBreak = true;
    this.messageObject.room = localStorage.getItem('room');
    this.messageObject.rating = event;
    this.messageObject.news_id = this.news_id;
    console.log('sending message: ');
    console.log(this.messageObject);
    this.newsRatingsService.sendMessage(this.messageObject);
    this.messageObject = {};
  }

  toast(msg, t = 4000) {
    const config = new MdSnackBarConfig();
    config.duration = t;
    this.snackBar.open(msg, 'Cerrar', config);
  }

}

ng-ratings.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { NgRatingsComponent } from './ng-ratings.component';
import { NgRatingsService } from './ng-ratings.service';

    @NgModule({
      imports: [
        CommonModule
      ],
      declarations: [NgRatingsComponent],
      exports: [NgRatingsComponent],
      providers: [NgRatingsService]
    })
    export class NgRatingsModule { } 

ng-ratings.component.html

<fieldset class="rating" >
    <input (click)="send('5')" type="radio" [checked]="checked_5" id="star5" name="rating" value="5" /><label class = "full" for="star5" title="Awesome - 5 stars"></label>
    <input (click)="send('4.5')" type="radio" [checked]="checked_45" id="star4half" name="rating" value="4 and a half" /><label class="half" for="star4half" title="Pretty good - 4.5 stars"></label>
    <input (click)="send('4')" type="radio" [checked]="checked_4" id="star4" name="rating" value="4" /><label class = "full" for="star4" title="Pretty good - 4 stars"></label>
    <input (click)="send('3.5')" type="radio" [checked]="checked_35" id="star3half" name="rating" value="3 and a half" /><label class="half" for="star3half" title="Meh - 3.5 stars"></label>
    <input (click)="send('3')" type="radio" [checked]="checked_3" id="star3" name="rating" value="3" /><label class = "full" for="star3" title="Meh - 3 stars"></label>
    <input (click)="send('2.5')" type="radio" [checked]="checked_25" id="star2half" name="rating" value="2 and a half" /><label class="half" for="star2half" title="Kinda bad - 2.5 stars"></label>
    <input (click)="send('2')" type="radio" [checked]="checked_2" id="star2" name="rating" value="2" /><label class = "full" for="star2" title="Kinda bad - 2 stars"></label>
    <input (click)="send('1.5')" type="radio" [checked]="checked_15" id="star1half" name="rating" value="1 and a half" /><label class="half" for="star1half" title="Meh - 1.5 stars"></label>
    <input (click)="send('1')" type="radio" [checked]="checked_1" id="star1" name="rating" value="1" /><label class = "full" for="star1" title="Sucks big time - 1 star"></label>
    <input (click)="send('0.5')" type="radio" [checked]="checked_05" id="starhalf" name="rating" value="half" /><label class="half" for="starhalf" title="Sucks big time - 0.5 stars"></label>
</fieldset>

ng-ratings.component.css

@import url(//netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.css);

fieldset, label { margin: 0; padding: 0; }
body{ margin: 20px; }
h1 { font-size: 1.5em; margin: 10px; }
/****** Style Star Rating Widget *****/
.rating { 
  border: none;
  float: left;
}

.rating > input { display: none; } 
.rating > label:before { 
  margin: 5px;
  font-size: 1.25em;
  font-family: FontAwesome;
  display: inline-block;
  content: "\f005";
}

.rating > .half:before { 
  content: "\f089";
  position: absolute;
}

.rating > label { 
  color: #ddd; 
 float: right; 
}

/***** CSS Magic to Highlight Stars on Hover *****/

.rating > input:checked ~ label, /* show gold star when clicked */
.rating:not(:checked) > label:hover, /* hover current star */
.rating:not(:checked) > label:hover ~ label { color: #FFD700;  } /* hover previous stars in list */

.rating > input:checked + label:hover, /* hover current star when changing rating */
.rating > input:checked ~ label:hover,
.rating > label:hover ~ input:checked ~ label, /* lighten current selection */
.rating > input:checked ~ label:hover ~ label { color: #FFED85;  } 

your.component.html

 <app-ng-ratings [ratingVal]="starsCount" [id]="id" > </app-ng-ratings>

In component.html you should have a starsCount variable that holds the weighted average of all votes.

And just in case you decide to use sockets with observables for real time updates here is the service:

ng-ratings.service.ts

import { Subject } from 'rxjs/Subject';
import { Observable } from 'rxjs/Observable';
import { AppSettings } from '../app.settings';
import * as io from 'socket.io-client';

export class NgRatingsService {
  private url = `${AppSettings.API_SOCKET_ENDPOINT}`;
  private socket;

  constructor() {
  }

  sendMessage(message) {
    this.socket.emit('rate-news', JSON.stringify(message));
  }

  getMessages() {
    const observable = new Observable(observer => {
      this.socket = io(this.url);
      this.socket.on('message', (data) => {
        observer.next(data);
      });
      return () => {
        this.socket.disconnect();
      };
    });
    return observable;
  }
}

Should work with a simple copy paste if you remove all references to socket.io and material.

Credit to James Barnett for his star rating code

Lucas
  • 9,871
  • 5
  • 42
  • 52
0

You can create a simple component to achieve this,

<rating-star max = 10 (onRating) = onRating($event)></rating-star>

Rating component

import { Component,Input,Output,EventEmitter  } from '@angular/core';

@Component({
  selector: 'rating-star',
  template: '<div>'
      +'<span class="icon" *ngFor = "let s of maxItem">'
         +'<i [ngClass]=" s <= this.ratedCount ? \'filled\' :\'\'\ " class="fa fa-star"' 
            +'aria-hidden="true" (click)="toggleRating(s)"></i>'
      +'</span>'
    +'</div>',
  styleUrls: ['./app.component.css']
})
export class RatingStarComponent {
 @Input() max: number;
 @Output() onRating = new EventEmitter<Number>();
 
 maxItem : any[];
 ratedCount : number;
 
 constructor(){
     this.ratedCount = 0;
 }
 
 ngOnInit(){
     this.maxItem = [];
     for(var i=0;i<this.max;i++){
         this.maxItem.push(i+1);
     }
 }
 toggleRating(s:number){
      this.ratedCount = s;
      this.onRating.emit(this.ratedCount);
 }

}

Parent component

onRating(rating : number){
    console.log(rating);
  }
Machavity
  • 30,841
  • 27
  • 92
  • 100
Prashobh
  • 9,216
  • 15
  • 61
  • 91
-1

this is something sass issue...

instead what you can do is import css file in your ' styles.css'

i.e.

do this in style.css

@import "~css-star-rating/dist/css/star-rating.css";

instead of

@import "~angular-star-rating/assets/scss/star-rating";