Selection
Calendar
Choose a date in a month view with calendar navigation.
Import
import { NeuCalendarComponent } from '@neural-ui/native/calendar';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.
Basic
Select a day to read its agenda. Add, edit or delete events in this local example; changes last only while the page is open.
View and copy the complete example
import { Component, signal } from '@angular/core';
import { NeuButtonComponent } from '@neural-ui/native/button';
import { NeuInputComponent } from '@neural-ui/native/input';
import { NeuCalendarComponent } from '@neural-ui/native/calendar';
import { NeuConfirmDialogComponent } from '@neural-ui/native/confirm-dialog';
import { NeuDateInputComponent } from '@neural-ui/native/date-input';
import { NeuModalComponent } from '@neural-ui/native/modal';
import { View, Text, ScrollView } from '@ng-native/components';
import type { NeuCalendarEvent } from '@neural-ui/native/calendar';
@Component({
selector: 'app-example',
imports: [NeuButtonComponent, NeuInputComponent, NeuCalendarComponent, NeuConfirmDialogComponent, NeuDateInputComponent, NeuModalComponent, View, Text, ScrollView],
template: `
<scroll-view class="calendar-scroll" keyboardShouldPersistTaps="handled"><view class="calendar-content"><neu-calendar
label="Team calendar" locale="en"
[(month)]="month" [(value)]="date" [events]="events()" [editable]="true"
(eventCreateRequested)="createEvent($event)"
(eventEditRequested)="editEvent($event)"
(eventDeleteRequested)="requestDelete($event)"
/></view></scroll-view>
<neu-modal [(open)]="editorOpen" [title]="editingId() ? 'Edit event' : 'Add event'">
<neu-input label="Event title" [(value)]="draftTitle" placeholder="Team planning" />
<neu-date-input label="Event date" locale="en" [(value)]="draftDate" />
<neu-input label="Details" [(value)]="draftDescription" placeholder="Optional details" />
@if (formError()) { <text accessibilityRole="alert">{{ formError() }}</text> }
<view class="actions">
<neu-button label="Save event" size="sm" (pressed)="saveEvent()" />
<neu-button label="Cancel" size="sm" variant="text" (pressed)="editorOpen.set(false)" />
</view>
</neu-modal>
<neu-confirm-dialog
[(open)]="deleteOpen" title="Delete event?"
[message]="'Remove ' + (deleting()?.label ?? 'this event') + ' from the calendar?'"
confirmLabel="Delete event" intent="danger" (confirmed)="deleteEvent()"
/>
`,
styles: `
.actions { gap: 12px; align-items: flex-start; } text { color: var(--neu-text, #172033); font-size: 16px; }
:host { flex: 1; min-height: 0; } .calendar-scroll { flex: 1; min-height: 0; } .calendar-content { padding-bottom: 20px; } .actions { flex-direction: row; flex-wrap: wrap; gap: 8px; }
`,
})
export class ExampleComponent {
readonly month = signal('2026-10');
readonly date = signal('2026-10-16');
readonly events = signal<readonly NeuCalendarEvent[]>([
{ id: 'review', label: 'Release review', description: 'Review the mobile release with the team', date: '2026-10-16' },
{ id: 'research', label: 'Customer interview', description: 'Discuss the next mobile experience', date: '2026-10-16' },
{ id: 'planning', label: 'Sprint planning', description: 'Plan the next iteration', date: '2026-10-20' },
]);
readonly editorOpen = signal(false);
readonly deleteOpen = signal(false);
readonly editingId = signal<string | null>(null);
readonly deleting = signal<NeuCalendarEvent | null>(null);
readonly draftTitle = signal('');
readonly draftDate = signal('');
readonly draftDescription = signal('');
readonly formError = signal('');
private nextEventId = 0;
createEvent(date: string): void {
this.editingId.set(null);
this.draftTitle.set('');
this.draftDate.set(date);
this.draftDescription.set('');
this.formError.set('');
this.editorOpen.set(true);
}
editEvent(event: NeuCalendarEvent): void {
this.editingId.set(event.id);
this.draftTitle.set(event.label);
this.draftDate.set(event.date);
this.draftDescription.set(event.description ?? '');
this.formError.set('');
this.editorOpen.set(true);
}
saveEvent(): void {
const label = this.draftTitle().trim();
const date = this.draftDate().trim();
const parsed = new Date(date + 'T00:00:00.000Z');
if (!label || !/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/.test(date) || Number.isNaN(parsed.getTime()) || parsed.toISOString().slice(0, 10) !== date) {
this.formError.set('Enter an event title and a valid date (YYYY-MM-DD).');
return;
}
const id = this.editingId();
const event: NeuCalendarEvent = { id: id ?? 'event-' + ++this.nextEventId, label, date, description: this.draftDescription().trim() };
this.events.update(events => id ? events.map(item => item.id === id ? event : item) : [...events, event]);
this.date.set(date);
this.editorOpen.set(false);
}
requestDelete(event: NeuCalendarEvent): void {
this.deleting.set(event);
this.deleteOpen.set(true);
}
deleteEvent(): void {
const id = this.deleting()?.id;
if (id) this.events.update(events => events.filter(event => event.id !== id));
this.deleteOpen.set(false);
this.deleting.set(null);
}
}Interactive playground
Change the settings and try the result.
Device captures shown in English.


API reference
Inputs
| Name | Type | Default | Binding | Description |
|---|---|---|---|---|
| label | string | 'Calendar' | Input | Human-readable name for the control, action or group. |
| locale | string | 'en' | Input | Locale used for calendar or date formatting, such as en or es. |
| firstDay | number | 1 | Input | First day of the calendar week: 0 is Sunday and 1 is Monday. |
| min | string | '' | Input | Earliest allowed date as YYYY-MM-DD. An empty string leaves this boundary unset. |
| max | string | '' | Input | Latest allowed date as YYYY-MM-DD. An empty string leaves this boundary unset. |
| disabled | boolean | false | Input | Disables user interaction. Values can still be supplied by the application. |
| readonly | boolean | false | Input | Prevents user editing or selection while retaining the current value. |
| previousLabel | string | 'Previous month' | Input | Text or accessible name used for previous. It does not perform the action by itself. |
| nextLabel | string | 'Next month' | Input | Text or accessible name used for next. It does not perform the action by itself. |
| previousYearLabel | string | 'Previous year' | Input | Accessible name for moving back one year in the month picker. |
| nextYearLabel | string | 'Next year' | Input | Accessible name for advancing one year in the month picker. |
| previousYearsLabel | string | 'Previous 12 years' | Input | Accessible name for the previous group of twelve years. |
| nextYearsLabel | string | 'Next 12 years' | Input | Accessible name for the next group of twelve years. |
| events | readonly NeuCalendarEvent[] | [] | Input | App-owned calendar entries. The date field uses YYYY-MM-DD. Dates containing events are marked; the selected date shows its agenda. The component never persists or deletes entries itself. |
| showAgenda | boolean | true | Input | Show the agenda below the calendar for a selected valid date. DateInput disables it for date-only picking. |
| editable | boolean | false | Input | Show Add, Edit and Delete actions in the agenda. They emit requests; your application implements the form, confirmation and persistence. The disabled and readonly states prevent these actions. |
| agendaLabel | string | 'Agenda' | Input | Heading for the selected date agenda. |
| emptyAgendaLabel | string | 'No events on this day' | Input | Message displayed when the selected date contains no events. |
| hasEventsLabel | string | 'Day with events' | Input | Accessible hint for dates containing events; the visible dot is decorative. |
| addEventLabel | string | 'Add event' | Input | Label for requesting a new event on the selected date. |
| editEventLabel | string | 'Edit' | Input | Visible action label and accessible prefix for editing an agenda event. |
| deleteEventLabel | string | 'Delete' | Input | Visible action label and accessible prefix for requesting deletion of an agenda event. |
Models
| Name | Type | Default | Binding | Description |
|---|---|---|---|---|
| value | string | '' | Model · two-way | Current edited value or selected ID(s), using the declared type. Bind a writable signal with [(value)]. |
| month | string | todayISO().slice(0, 7) | Model · two-way | Current calendar month as YYYY-MM. Bind a writable signal with [(month)]. |
Outputs
| Name | Payload | When it emits |
|---|---|---|
| valueChange | string | Emits the updated value value. [(value)] binds this output together with its model input. |
| monthChange | string | Emits the updated month value. [(month)] binds this output together with its model input. |
| eventCreateRequested | string | Requests a new event for the selected YYYY-MM-DD date. The app opens its editor and updates events after saving. |
| eventEditRequested | NeuCalendarEvent | Emits the selected agenda entry to edit. No event data is changed by Calendar. |
| eventDeleteRequested | NeuCalendarEvent | Emits the agenda entry requested for deletion. Your application confirms and removes it; Calendar does not delete it. |
| touch | void | Reports user interaction to the surrounding form or application. |
Model state
Bind the signal with [(modelName)] without calling it. Use modelName() to read its value.
import { signal } from '@angular/core';
// Fields inside your component class
readonly value = signal<string>('');
readonly month = signal<string>(new Date().toISOString().slice(0, 7));Types and data interfaces
Use the imports in your application. The definitions below are provided for reference.
NeuCalendarEvent
import type { NeuCalendarEvent } from '@neural-ui/native/calendar';
import type { NeuOption } from '@neural-ui/native';
// Public definition for reference only. Import this type; do not redeclare it.
export interface NeuCalendarEvent extends NeuOption {
readonly date: string;
}| Field | Type | Requirement | Meaning |
|---|---|---|---|
| date | string | Required | Date associated with the item; Calendar expects YYYY-MM-DD. |
| id | string | Required | Stable, unique identifier used for tracking and selection. |
| label | string | Required | Human-readable item name. |
| description | string | Optional | Optional supporting text; rendering depends on the control. |
| disabled | boolean | Optional | Prevents activating or selecting this item. |
NeuOption
import type { NeuOption } from '@neural-ui/native';
// Public definition for reference only. Import this type; do not redeclare it.
export interface NeuOption {
readonly id: string;
readonly label: string;
readonly description?: string;
readonly disabled?: boolean;
}| Field | Type | Requirement | Meaning |
|---|---|---|---|
| id | string | Required | Stable, unique identifier used for tracking and selection. |
| label | string | Required | Human-readable item name. |
| description | string | Optional | Optional supporting text; rendering depends on the control. |
| disabled | boolean | Optional | Prevents activating or selecting this item. |