Installation
import { WrRating } from 'ngwr/rating';
@Component({ imports: [WrRating] })
export class MyComponent {
protected readonly score = signal<number | null>(0);
}Basic
<wr-rating [(value)]="score" />Half stars
step="0.5" enables half-star granularity (hover the left half of a star).
<wr-rating [(value)]="score" step="0.5" />Custom count
<wr-rating [(value)]="score" [count]="10" />Read-only
Use to display an existing rating without interaction.
<wr-rating [value]="4.5" step="0.5" [readonly]="true" />Values outside the range
[0, count] bounds what a click or an arrow key can produce. A value written from OUTSIDE — a form loaded from an API, a model seeded by a query string — is drawn and announced clamped, because a role="slider" cannot report a position past its own maximum, and is left in the model exactly as it stands.
The control does not write the clamp back, and that is the same rule wr-slider and wr-input-number follow. Under [formField] a write the component makes to its own value is indistinguishable from the user moving the stars, so writing back would mark a pristine form dirty on first paint — tripping unsaved-changes guards and opening every validator message before anything had been touched — and would delete the out-of-range value that a max() rule exists to report. The first real interaction commits an in-range number, and the two agree from then on.
The reactive-forms guide has the same table for every value control, beside the two bridge behaviours that catch people out more often: updateOn does not apply to an ngwr control, and a { emitEvent: false } write does not repaint one.
API
| Name | Description | Type | Default |
|---|---|---|---|
count | Total number of slots. | number | 5 |
step | Step granularity — 1 for whole stars, 0.5 for halves. | 0.5 | 1 | 1 |
readonly | Read-only — value is displayed but not interactive. | boolean | false |
disabled | Disable interaction. Bound automatically from the field's disabled state when used with [formField]. | boolean | false |
size | Control size — scales the icons + gaps. | WrRatingSize | 'md' |
ariaLabel | Accessible label. Falls back to rating.label, then 'Rating'. | string | null | null |
value | The rating. Bound by [formField], or two-way via [(value)]. | number | null | null |
(touch) | Emitted on blur so a bound field can mark itself touched. | void | — |
CSS variables
Custom properties ngwr/rating publishes. Each default below is declared on the component's own selector, so a :root override is shadowed by it — set them on that selector, on a wrapper you scope yourself, or inline on the element. Unlike the BEM class names, these are the supported way to restyle the component.
| Variable | Default | Declared on |
|---|---|---|
--wr-rating-empty | var(--wr-color-outline) | .wr-rating |
--wr-rating-filled | var(--wr-color-warning, #ffba00) | .wr-rating |
--wr-rating-gap | 0.125rem | .wr-rating +2 variant overrides |
--wr-rating-size | 1.25rem | .wr-rating +2 variant overrides |