Skip to main content
Neural Nativev0.1.0-beta.1Documentation

Import

component.ts
import { NeuRatingComponent } from '@neural-ui/native/rating';

Examples

Import ExampleComponent into its parent and place <app-example /> inside your application’s root neu-theme. The preview supplies the device frame and safe areas; use the root setup from Installation in your app.

Worth another morning?

Rate a shared forest walk using the real five-star control and read the matching reflection. Clear resets the draft to zero; saving keeps a separate local score until you choose to save another one. No feedback is sent.

View and copy the complete example
basic.component.ts
import { Component, signal } from '@angular/core';
import { NeuButtonComponent } from '@neural-ui/native/button';
import { NeuRatingComponent } from '@neural-ui/native/rating';
import { View, Text, Image, ScrollView } from '@ng-native/components';

@Component({
  selector: 'app-example',
  imports: [NeuButtonComponent, NeuRatingComponent, View, Text, Image, ScrollView],
  template: `
    <scroll-view class="product-scroll" keyboardShouldPersistTaps="handled" [showsVerticalScrollIndicator]="false"><view class="product-stack"><view class="product-section"><text class="product-title" accessibilityRole="header">Worth another morning?</text><text class="product-caption">A small reflection on time well spent</text></view>
    <view class="walk-summary"><image class="walk-cover" [source]="{ uri: cover }" resizeMode="cover" accessibilityLabel="Original illustration of a sunlit forest path" /><view class="walk-heading"><text class="walk-kicker">NEURAL WALKS / 01</text><text class="walk-title">The slower morning</text><text class="walk-description">Forest route · 45 minutes together</text></view></view>
    <view class="product-surface"><view class="product-section"><text class="product-heading">How did it feel?</text><text class="product-caption">Your impression helps shape the next studio walk.</text></view><neu-rating label="Rate your experience" clearLabel="Clear rating" [(value)]="rating" [max]="5" [clearable]="true" />
    <view class="rating-reflection"><text class="reflection-kicker">YOUR IMPRESSION</text><text class="reflection-copy" accessibilityLiveRegion="polite">{{ rating() ? feedback()[rating() - 1] : 'A fresh page. Choose your stars.' }}</text></view>
    <neu-button label="Save my impression" [disabled]="rating() === 0 || rating() === submitted()" (pressed)="submitted.set(rating())" />
    @if (submitted()) { <text class="product-caption" accessibilityLiveRegion="polite">Saved on this screen: {{ submitted() }} / 5. Thank you for taking a moment.</text> }</view></view></scroll-view>
  `,
  styles: `
.actions { gap: 12px; align-items: flex-start; } text { color: var(--neu-text, #172033); font-size: 16px; }

:host { flex: 1; flex-shrink: 1; min-height: 0; }
.product-scroll { flex: 1; flex-shrink: 1; height: 0px; min-height: 0; }
.product-stack { gap: 24px; padding-bottom: 20px; }
.product-section { gap: 12px; }
.product-row { flex-direction: row; align-items: center; gap: 12px; }
.product-copy { flex: 1; min-width: 0; gap: 4px; }
.product-title { color: var(--neu-text, #172033); font-size: 24px; line-height: 30px; font-weight: 600; }
.product-heading { color: var(--neu-text, #172033); font-size: 17px; line-height: 23px; font-weight: 600; }
.product-caption { color: var(--neu-muted, #596477); font-size: 14px; line-height: 20px; }
.product-actions { flex-direction: row; flex-wrap: wrap; align-items: center; gap: 8px; }
.product-surface { gap: 16px; padding: 16px; border-radius: 16px; background-color: var(--neu-surface, #ffffff); border-width: 1px; border-color: var(--neu-border, #a5afbf); }
.walk-summary { overflow: hidden; border-radius: 18px; background-color: #e6efe7; }
.walk-cover { width: 100%; aspect-ratio: 2.8; }
.walk-heading { gap: 7px; padding: 18px; }
.walk-kicker { color: #3f5c45; font-size: 10px; line-height: 16px; font-weight: 600; letter-spacing: 1px; }
.walk-title { color: #274531; font-size: 23px; line-height: 29px; font-weight: 600; }
.walk-description { color: #3f5c45; font-size: 12px; line-height: 18px; }
.rating-reflection { min-height: 78px; gap: 8px; padding: 14px; border-radius: 12px; background-color: var(--neu-surface-secondary, #eef1f5); }
.reflection-kicker { color: var(--neu-muted, #596477); font-size: 9px; line-height: 14px; font-weight: 600; letter-spacing: 1px; }
.reflection-copy { color: var(--neu-text, #172033); font-size: 15px; line-height: 22px; font-weight: 500; }
  `,
})
export class ExampleComponent {
  readonly cover = '/assets/media/v2/forest.png';
  readonly rating = signal(4);
  readonly submitted = signal(0);
  readonly feedback = signal(['Not quite my kind of morning.', 'Some good moments, with room to improve.', 'A welcome change of scenery.', 'A little pause that made a difference.', 'More mornings like this, please.']);
}

Read-only summary

Present an average customer rating without editable stars.

View and copy the complete example
read-only-summary.component.ts
import { Component, signal } from '@angular/core';
import { NeuRatingComponent } from '@neural-ui/native/rating';
import { View, Text, ScrollView } from '@ng-native/components';

@Component({
  selector: 'app-example',
  imports: [NeuRatingComponent, View, Text, ScrollView],
  template: `
    <scroll-view class="usage-scroll" keyboardShouldPersistTaps="handled"><view class="usage-stack">
    <neu-rating label="Average customer rating" [value]="4" [max]="5" [readonly]="true" [clearable]="false" /><text class="usage-caption">4 out of 5 · 128 reviews</text>
    </view></scroll-view>
  `,
  styles: `
.actions { gap: 12px; align-items: flex-start; } text { color: var(--neu-text, #172033); font-size: 16px; }

.usage-scroll { flex: 1; }
.usage-stack { gap: 20px; padding-bottom: 20px; }
.usage-section { gap: 12px; }
.usage-heading { color: var(--neu-text, #172033); font-size: 16px; font-weight: 600; }
.usage-caption { color: var(--neu-muted, #64748b); font-size: 14px; }
.usage-row { flex-direction: row; flex-wrap: wrap; gap: 12px; align-items: center; }
.usage-actions { flex-direction: row; flex-wrap: wrap; gap: 8px; align-items: center; }


  `,
})
export class ExampleComponent {
  readonly rating = signal(3);
}
Interactive playground

Change the settings and try the result.

Device captures shown in English.

Rating · android · native capture
AndroidNative screenshot
Rating · ios · native capture
iOSNative screenshot

API reference

Inputs

NameTypeDefaultBindingDescription
labelstringRequiredInputHuman-readable name for the control, action or group.
maxnumber5InputNumber of positions on the rating scale.
disabledbooleanfalseInputDisables user interaction. Values can still be supplied by the application.
readonlybooleanfalseInputPrevents user editing or selection while retaining the current value.
clearablebooleantrueInputAllows clearing the selected value through the control’s clear action.
clearLabelstring'Clear rating'InputText or accessible name used for clear. It does not perform the action by itself.

Models

NameTypeDefaultBindingDescription
valuenumber0Model · two-wayCurrent edited value or selected ID(s), using the declared type. Bind a writable signal with [(value)].

Outputs

NamePayloadWhen it emits
valueChangenumberEmits the updated value value. [(value)] binds this output together with its model input.
touchvoidReports user interaction to the surrounding form or application.

Model state

Bind the signal with [(modelName)] without calling it. Use modelName() to read its value.

model-fields.ts
import { signal } from '@angular/core';

// Fields inside your component class
readonly value = signal<number>(0);