Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to Angular 17, use standalone components and new Angular control flow #127

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,5 @@ Thumbs.db

# angular-star-rating
@packaged/*

.nx/cache
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.cache
dist
CHANGELOG.md
/.nx/cache
13 changes: 6 additions & 7 deletions apps/demos/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,36 +103,35 @@
"serve": {
"executor": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "demos:build"
"buildTarget": "demos:build"
},
"configurations": {
"production": {
"browserTarget": "demos:build:production"
"buildTarget": "demos:build:production"
},
"test": {
"browserTarget": "demos:build:test"
"buildTarget": "demos:build:test"
},
"development": {
"browserTarget": "demos:build:development"
"buildTarget": "demos:build:development"
}
}
},
"extract-i18n": {
"executor": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "demos:build"
"buildTarget": "demos:build"
}
},
"test": {
"executor": "@nx/jest:jest",
"options": {
"jestConfig": "apps/demos/jest.config.ts",
"passWithNoTests": true,
"codeCoverage": true
}
},
"lint": {
"executor": "@nx/linter:eslint",
"executor": "@nx/eslint:lint",
"options": {
"lintFilePatterns": ["apps/demos/**/*.ts", "apps/demos/**/*.html"]
}
Expand Down
16 changes: 15 additions & 1 deletion libs/angular-star-rating/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,21 @@
{
"allow": []
}
]
],
"@typescript-eslint/explicit-member-accessibility": [
"error",
{
"accessibility": "explicit",
"overrides": {
"accessors": "explicit",
"constructors": "off",
"methods": "explicit",
"properties": "explicit",
"parameterProperties": "explicit"
}
}
],
"@angular-eslint/prefer-standalone-component": "error"
}
},
{
Expand Down
1 change: 0 additions & 1 deletion libs/angular-star-rating/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@
"peerDependencies": {
"@angular/core": ">=10.0.0",
"@angular/forms": ">=10.0.0",
"rxjs": ">=6.5.5",
"css-star-rating": ">=1.3.1"
}
}
3 changes: 1 addition & 2 deletions libs/angular-star-rating/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"sourceRoot": "libs/angular-star-rating/src",
"targets": {
"lint": {
"executor": "@nx/linter:eslint",
"executor": "@nx/eslint:lint",
"options": {
"lintFilePatterns": [
"libs/angular-star-rating/**/*.ts",
Expand All @@ -17,7 +17,6 @@
"executor": "@nx/jest:jest",
"options": {
"jestConfig": "libs/angular-star-rating/jest.config.ts",
"passWithNoTests": true,
"codeCoverage": true
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { CommonModule } from '@angular/common';
import { ModuleWithProviders, NgModule } from '@angular/core';

import { StarRatingComponent } from './components/star-rating/star-rating.component';
Expand All @@ -9,19 +8,18 @@ const DECLARATIONS = [StarRatingComponent, StarRatingControlComponent];
const EXPORTS = [DECLARATIONS];

@NgModule({
imports: [CommonModule],
declarations: [DECLARATIONS],
imports: DECLARATIONS,
exports: [EXPORTS],
})
export class StarRatingModule {
static forRoot(): ModuleWithProviders<StarRatingModule> {
public static forRoot(): ModuleWithProviders<StarRatingModule> {
return {
ngModule: StarRatingModule,
providers: [StarRatingConfigService],
};
}

static forChild(): ModuleWithProviders<StarRatingModule> {
public static forChild(): ModuleWithProviders<StarRatingModule> {
return {
ngModule: StarRatingModule,
providers: [],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
<div id="{{id}}" class="rating {{getComponentClassNames()}}" tabindex="0"
(keydown)="onKeyDown($event)" (blur)="onBlur($event)"
(focus)="onFocus($event)" (mouseleave)="onStarHover(0)">
<div *ngIf="labelText" class="label-value">{{labelText}}</div>
<div [id]="id" class="rating {{ getComponentClassNames() }}" tabindex="0"
(keydown)="onKeyDown($event)" (blur)="onBlur($event)" (focus)="onFocus($event)" (mouseleave)="onStarHover(0)">
@if (labelText) {
<div class="label-value">{{ labelText }}</div>
}
<div class="star-container">
<div class="star" (mouseenter)="onStarHover(star)"
*ngFor="let star of stars" (click)="onStarClicked(star)">
<i *ngIf="!svgVisible()" class="star-empty {{classEmpty}}"></i>
<i *ngIf="!svgVisible()" class="star-half {{classHalf}}"></i>
<i *ngIf="!svgVisible()" class="star-filled {{classFilled}}"></i>
<svg *ngIf="svgVisible()" class="star-empty">
<use xmlns:xlink="http://www.w3.org/1999/xlink"
[attr.xlink:href]="pathEmpty"></use>
</svg>
<svg *ngIf="svgVisible()" class="star-half">
<use xmlns:xlink="http://www.w3.org/1999/xlink"
[attr.xlink:href]="pathHalf"></use>
</svg>
<svg *ngIf="svgVisible()" class="star-filled">
<use xmlns:xlink="http://www.w3.org/1999/xlink"
[attr.xlink:href]="pathFilled"></use>
</svg>
</div>
@for (star of stars;track star) {
<div class="star" (mouseenter)="onStarHover(star)" (click)="onStarClicked(star)">
@if (!svgVisible()) {
<i class="star-empty {{ classEmpty }}"></i>
<i class="star-half {{ classHalf }}"></i>
<i class="star-filled {{ classFilled }}"></i>
} @else {
<svg class="star-empty">
<use [attr.xlink:href]="pathEmpty"></use>
</svg>
<svg class="star-half">
<use [attr.xlink:href]="pathHalf"></use>
</svg>
<svg class="star-filled">
<use [attr.xlink:href]="pathFilled"></use>
</svg>
}
</div>
}
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -12,59 +12,59 @@ import { StarRatingUtils } from '../../services/star-rating.utils';
const STAR_RATING_CONTROL_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => StarRatingControlComponent),
multi: true,
multi: true
};

@Component({
selector: 'star-rating-control',
standalone: true,
providers: [STAR_RATING_CONTROL_ACCESSOR],
templateUrl: 'star-rating-control.component.html',
templateUrl: 'star-rating-control.component.html'
})
export class StarRatingControlComponent
extends StarRating
implements ControlValueAccessor
{
implements ControlValueAccessor {
@Output()
starClickChange: EventEmitter<ClickEvent> = new EventEmitter<ClickEvent>();
public starClickChange: EventEmitter<ClickEvent> = new EventEmitter<ClickEvent>();

@Output()
ratingChange: EventEmitter<RatingChangeEvent> = new EventEmitter<RatingChangeEvent>();
public ratingChange: EventEmitter<RatingChangeEvent> = new EventEmitter<RatingChangeEvent>();

@Output()
hoverRatingChange: EventEmitter<HoverRatingChangeEvent> = new EventEmitter<HoverRatingChangeEvent>();
public hoverRatingChange: EventEmitter<HoverRatingChangeEvent> = new EventEmitter<HoverRatingChangeEvent>();

// eslint-disable-next-line @typescript-eslint/ban-types
onTouch: Function;
private onTouch: Function;
// eslint-disable-next-line @typescript-eslint/ban-types
onModelChange: Function;
private onModelChange: Function;
private onModelChangeRegistered = false;
private onTouchRegistered = false;

saveOnClick($event: ClickEvent) {
protected saveOnClick($event: ClickEvent) {
if (this.starClickChange) {
this.starClickChange.emit($event);
}
}

saveOnRatingChange($event: RatingChangeEvent) {
protected saveOnRatingChange($event: RatingChangeEvent) {
if (this.ratingChange) {
this.ratingChange.emit($event);
}
}

saveOnHover($event: HoverRatingChangeEvent) {
protected saveOnHover($event: HoverRatingChangeEvent) {
if (this.hoverRatingChange) {
this.hoverRatingChange.emit($event);
}
}

saveOnTouch() {
protected saveOnTouch() {
if (this.onTouchRegistered) {
this.onTouch();
}
}

saveOnModelChange(value: number) {
protected saveOnModelChange(value: number) {
if (this.onModelChangeRegistered) {
this.onModelChange(value);
}
Expand All @@ -73,7 +73,7 @@ export class StarRatingControlComponent
/**ACCESSIBILITY **/

//Keyboard events
onKeyDown(event: KeyboardEvent) {
protected onKeyDown(event: KeyboardEvent) {
if (!this.interactionPossible()) {
return;
}
Expand All @@ -92,7 +92,7 @@ export class StarRatingControlComponent
//Reset
Backspace: () => this.reset(),
Delete: () => this.reset(),
Digit0: () => this.reset(),
Digit0: () => this.reset()
};

const handleDigits = (eventCode: string): void => {
Expand Down Expand Up @@ -121,22 +121,22 @@ export class StarRatingControlComponent
}

//Focus events
onBlur(event: FocusEvent) {
protected onBlur(event: FocusEvent) {
this.focus = false;
event.preventDefault();
event.stopPropagation();
this.saveOnTouch();
}

onFocus(event: FocusEvent) {
protected onFocus(event: FocusEvent) {
this.focus = true;
event.preventDefault();
event.stopPropagation();
this.saveOnTouch();
}

//Hover events
onStarHover(rating?: number): void {
protected onStarHover(rating?: number): void {
if (!this.interactionPossible() || !this.hoverEnabled) {
return;
}
Expand All @@ -150,16 +150,16 @@ export class StarRatingControlComponent

/**Form Control - ControlValueAccessor implementation**/

writeValue(obj: any): void {
public writeValue(obj: any): void {
this.rating = obj;
}

registerOnChange(fn: any): void {
public registerOnChange(fn: any): void {
this.onModelChange = fn;
this.onModelChangeRegistered = true;
}

registerOnTouched(fn: any): void {
public registerOnTouched(fn: any): void {
this.onTouch = fn;
this.onTouchRegistered = true;
}
Expand All @@ -169,7 +169,7 @@ export class StarRatingControlComponent
}

//Overrides
setRating(value: number): void {
public setRating(value: number): void {
const initValue = this.rating;
super.setRating(value);

Expand All @@ -192,7 +192,7 @@ export class StarRatingControlComponent
*
* @param rating
*/
onStarClicked(rating: number): void {
protected onStarClicked(rating: number): void {
//fire onClick event
if (!this.interactionPossible()) {
return;
Expand All @@ -201,7 +201,7 @@ export class StarRatingControlComponent
this.rating = rating;

const onClickEventObject: ClickEvent = {
rating: this.rating,
rating: this.rating
};
this.saveOnClick(onClickEventObject);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
<div id="{{id}}" class="rating {{getComponentClassNames()}}" tabindex="0"
(keydown)="onKeyDown($event)" (mouseleave)="onStopHover()">
<div *ngIf="labelText" class="label-value">{{labelText}}</div>
<div [id]="id" class="rating {{ getComponentClassNames() }}" tabindex="0" (keydown)="onKeyDown($event)" (mouseleave)="onStopHover()">
@if (labelText) {
<div class="label-value">{{ labelText }}</div>
}
<div class="star-container">
<div class="star" (mouseenter)="onStarHover(star)"
*ngFor="let star of stars" (click)="onStarClicked(star)">
<i *ngIf="!svgVisible()" class="star-empty {{classEmpty}}"></i>
<i *ngIf="!svgVisible()" class="star-half {{classHalf}}"></i>
<i *ngIf="!svgVisible()" class="star-filled {{classFilled}}"></i>
<svg *ngIf="svgVisible()" class="star-empty">
<use xmlns:xlink="http://www.w3.org/1999/xlink"
[attr.xlink:href]="pathEmpty"></use>
</svg>
<svg *ngIf="svgVisible()" class="star-half">
<use xmlns:xlink="http://www.w3.org/1999/xlink"
[attr.xlink:href]="pathHalf"></use>
</svg>
<svg *ngIf="svgVisible()" class="star-filled">
<use xmlns:xlink="http://www.w3.org/1999/xlink"
[attr.xlink:href]="pathFilled"></use>
</svg>
</div>
@for (star of stars;track star) {
<div class="star" (mouseenter)="onStarHover(star)" (click)="onStarClicked(star)">
@if (!svgVisible()) {
<i class="star-empty {{ classEmpty }}"></i>
<i class="star-half {{ classHalf }}"></i>
<i class="star-filled {{ classFilled }}"></i>
} @else {
<svg class="star-empty">
<use [attr.xlink:href]="pathEmpty"></use>
</svg>
<svg class="star-half">
<use [attr.xlink:href]="pathHalf"></use>
</svg>
<svg class="star-filled">
<use [attr.xlink:href]="pathFilled"></use>
</svg>
}
</div>
}
</div>
</div>
Loading