在 angular-4 中导入 angular-star-rating 时出现问题

Issue while importing angular-star-rating in angular-4

我正在尝试在我的 angular4 项目中使用 angular-star-rating,该项目是在 angular CLI 的帮助下生成的。我正在使用 bootstrap-4。 我已遵循此文档 [URL] https://www.npmjs.com/package/angular-star-rating 我遵循的步骤:

  1. npm install angular-star-rating --save
  2. 已将图像从 ./node_modules/angular-star-rating/assets/images 文件夹复制到 ./src/assets/images。
  3. 在style.css中,@import "~angular-star-rating/assets/scss/star-rating";
  4. 在app.module中,从'angular-star-rating'导入{StarRatingModule};
  5. 然后在导入数组中,指定库

我的文件夹结构是这样的 我得到的错误与 style.css 文件有关,即第 3 步。 可能无法找到 "~angular-star-rating/assets/scss/star-rating";

中存在的 scss 文件

我也试过输入绝对路径,但也没用。

那个库似乎已经过时了,也破坏了我的项目。我看到了您的回答,因为我也在寻找星级评分解决方案,因此我将与您分享我非常简单但有效的解决方案,而无需使用任何 npm 模块,以便您可以在项目中改进它。请记住,我的解决方案适用于服务中的 socket.io 和可观察对象,因此您需要实施它,或者更简单地使用您自己的代码删除对 socket.io 和 material 模块的所有引用。代码很丑陋,但它会让你继续:

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>

在 component.html 中,您应该有一个 starsCount 变量,它包含所有投票的 weighted average

以防万一您决定使用带可观察对象的套接字进行实时更新,这里有服务:

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;
  }
}

如果您删除对 socket.io 和 material 的所有引用,应该可以使用简单的复制粘贴。

感谢 James Barnett 的 star rating code

您可以创建一个简单的组件来实现这一点,

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

评级组件

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);
 }

}

父组件

onRating(rating : number){
    console.log(rating);
  }

这是 sass 问题...

相反,你可以做的是 在您的“styles.css”

中导入 css 文件

在 style.css

中执行此操作

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

而不是

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

这个问题是版本不兼容导致的。在 package.json

中修复 angular-star-ratingcss-star-rating
"angular-star-rating": "3.0.8",
"css-star-rating": "1.1.3"