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

Import

component.ts
import { NeuTreeSelectComponent } from '@neural-ui/native/tree-select';

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.

Give your work a home

Open a hierarchical selector, expand its branches and select a department. The workspace card reflects the selected leaf’s name.

View and copy the complete example
basic.component.ts
import { Component, signal, computed } from '@angular/core';
import { NeuCardComponent } from '@neural-ui/native/card';
import { NeuTreeSelectComponent } from '@neural-ui/native/tree-select';
import { View, Text, ScrollView } from '@ng-native/components';
import type { NeuTreeNode } from '@neural-ui/native';

@Component({
  selector: 'app-example',
  imports: [NeuCardComponent, NeuTreeSelectComponent, View, Text, ScrollView],
  template: `
    <scroll-view class="product-scroll" keyboardShouldPersistTaps="handled" [showsVerticalScrollIndicator]="true"><view class="product-stack"><view class="product-section"><text class="product-title" accessibilityRole="header">Give your work a home</text><text class="product-caption">Choose a department without losing the structure</text></view>
    <view class="product-surface"><neu-tree-select label="Department" [nodes]="nodes" [(value)]="selected" [leafOnly]="true" placeholder="Choose a department" />
    <text class="product-caption">Expand Product to see its teams.</text></view>
    <neu-card title="Department workspace" [description]="departmentLabel()" variant="outlined"><text class="product-caption">New projects will use this department in this local example.</text></neu-card></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); }

  `,
})
export class ExampleComponent {
  readonly nodes: readonly NeuTreeNode[] = [
    { id: 'product', label: 'Product', children: [
      { id: 'design', label: 'Design' },
      { id: 'engineering', label: 'Engineering' },
    ] },
    { id: 'operations', label: 'Operations' },
  ];
  readonly selected = signal('design');
  readonly departmentLabel = computed(() => this.nodes.flatMap(node => node.children?.length ? node.children : [node]).find(node => node.id === this.selected())?.label || '');
}

Read-only department

Show a department that cannot be changed in this screen.

View and copy the complete example
selection-and-availability.component.ts
import { Component } from '@angular/core';
import { NeuTreeSelectComponent } from '@neural-ui/native/tree-select';
import { View, ScrollView } from '@ng-native/components';
import type { NeuTreeNode } from '@neural-ui/native';

@Component({
  selector: 'app-example',
  imports: [NeuTreeSelectComponent, View, ScrollView],
  template: `
    <scroll-view class="usage-scroll" keyboardShouldPersistTaps="handled"><view class="usage-stack">
    <neu-tree-select label="Locked department" [nodes]="nodes" value="design" [readonly]="true" />
    </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 nodes: readonly NeuTreeNode[] = [
    { id: 'product', label: 'Product', children: [
      { id: 'design', label: 'Design' },
      { id: 'engineering', label: 'Engineering' },
    ] },
    { id: 'operations', label: 'Operations' },
  ];
}
Interactive playground

Change the settings and try the result.

Device captures shown in English.

Tree Select · android · native capture
AndroidNative screenshot
Tree Select · ios · native capture
iOSNative screenshot

API reference

Inputs

NameTypeDefaultBindingDescription
nodesreadonly NeuTreeNode[][]InputHierarchical nodes with optional children. Keep IDs unique across the whole tree.
leafOnlybooleantrueInputRestricts selectable values to leaf nodes; parent nodes still organize the hierarchy.
placeholderstring'Choose item'InputExample or prompt displayed while the value is empty; keep a separate label.
closeLabelstring'Dismiss options'InputText or accessible name used for close. It does not perform the action by itself.
expandLabelstring'Expand'InputText or accessible name used for expand. It does not perform the action by itself.
emptyLabelstring'No items'InputText or accessible name used for empty state. It does not perform the action by itself.
labelstringRequiredInputHuman-readable name for the control, action or group.
disabledbooleanfalseInputDisables user interaction. Values can still be supplied by the application.
readonlybooleanfalseInputPrevents user editing or selection while retaining the current value.
invalidbooleanfalseInputMarks the control invalid. Your form or application supplies the validation rule.
touchedbooleanfalseInputField interaction state, supplied manually or through Signal Forms.
hintstring''InputField guidance shown when no error message is being displayed.
requiredbooleanfalseInputRequired-field presentation. Define the actual validation rule in your application form.
requiredLabelstring'Required'InputLocalized requirement announced with the field hint when required is true. Defaults to Required; it does not validate the value.
errorstring''InputApplication-provided error message; combine it with the control’s invalid state.

Models

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

Outputs

NamePayloadWhen it emits
valueChangestringEmits 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<string>('');

Types and data interfaces

Use the imports in your application. The definitions below are provided for reference.

NeuOption

NeuOption.ts
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;
}
FieldTypeRequirementMeaning
idstringRequiredStable, unique identifier used for tracking and selection.
labelstringRequiredHuman-readable item name.
descriptionstringOptionalOptional supporting text; rendering depends on the control.
disabledbooleanOptionalPrevents activating or selecting this item.

NeuTreeNode

NeuTreeNode.ts
import type { NeuTreeNode } from '@neural-ui/native';
import type { NeuOption } from '@neural-ui/native';

// Public definition for reference only. Import this type; do not redeclare it.
export interface NeuTreeNode extends NeuOption {
    readonly children?: readonly NeuTreeNode[];
}
FieldTypeRequirementMeaning
childrenreadonly NeuTreeNode[]OptionalRecursive child nodes; omit for a leaf.
idstringRequiredStable, unique identifier used for tracking and selection.
labelstringRequiredHuman-readable item name.
descriptionstringOptionalOptional supporting text; rendering depends on the control.
disabledbooleanOptionalPrevents activating or selecting this item.