在 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
我遵循的步骤:
- npm install angular-star-rating --save
- 已将图像从 ./node_modules/angular-star-rating/assets/images 文件夹复制到 ./src/assets/images。
- 在style.css中,@import "~angular-star-rating/assets/scss/star-rating";
- 在app.module中,从'angular-star-rating'导入{StarRatingModule};
- 然后在导入数组中,指定库
我的文件夹结构是这样的
我得到的错误与 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-rating
和 css-star-rating
"angular-star-rating": "3.0.8",
"css-star-rating": "1.1.3"
我正在尝试在我的 angular4 项目中使用 angular-star-rating,该项目是在 angular CLI 的帮助下生成的。我正在使用 bootstrap-4。 我已遵循此文档 [URL] https://www.npmjs.com/package/angular-star-rating 我遵循的步骤:
- npm install angular-star-rating --save
- 已将图像从 ./node_modules/angular-star-rating/assets/images 文件夹复制到 ./src/assets/images。
- 在style.css中,@import "~angular-star-rating/assets/scss/star-rating";
- 在app.module中,从'angular-star-rating'导入{StarRatingModule};
- 然后在导入数组中,指定库
我的文件夹结构是这样的
我也试过输入绝对路径,但也没用。
那个库似乎已经过时了,也破坏了我的项目。我看到了您的回答,因为我也在寻找星级评分解决方案,因此我将与您分享我非常简单但有效的解决方案,而无需使用任何 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-rating
和 css-star-rating
"angular-star-rating": "3.0.8",
"css-star-rating": "1.1.3"