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

Import

component.ts
import { NeuFormFieldComponent } from '@neural-ui/native/form-field';

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.

Invite your next teammate

Enter an invitation email and validate it. The wrapper surrounds a real projected TextInput with one label, hint and error; it does not create a second input.

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

@Component({
  selector: 'app-example',
  imports: [NeuButtonComponent, NeuFormFieldComponent, View, Text, TextInput, 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">Invite your next teammate</text><text class="product-caption">A clear label, helpful guidance and recoverable errors</text></view><view class="product-surface"><neu-form-field #emailField label="Email address" hint="We will use this address for invitations" [required]="true" [invalid]="invalid()" error="Enter a valid email address.">
      <text-input class="projected-control" [class.invalid]="invalid()"
        accessibilityLabel="Email address (required)"
        [accessibilityLabelledBy]="emailField.labelId"
        [accessibilityHint]="invalid() ? 'Enter a valid email address.' : 'We will use this address for invitations'"
        keyboardType="email-address" autoCapitalize="none" [autoCorrect]="false"
        [invalid]="invalid()" [touched]="attempted()" [(value)]="email" />
    </neu-form-field>
    <view class="field-actions">
      <neu-button label="Check email" size="sm" (pressed)="attempted.set(true)" />
    </view></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); }
.projected-control {
  min-height: 48px;
  padding: 12px 14px;
  font-size: var(--neu-font-size, 16px);
  color: var(--neu-text, #172033);
  background-color: var(--neu-surface, #ffffff);
  border-width: 1px;
  border-color: var(--neu-border, #a5afbf);
  border-radius: var(--neu-radius, 12px);
}
.projected-control.invalid {
  border-color: var(--neu-danger, #b3261e);
}

.field-actions { padding-top: 16px; align-items: flex-start; }
  `,
})
export class ExampleComponent {
  readonly email = signal('alex@example.com');
  readonly attempted = signal(false);
  readonly invalid = computed(() => this.attempted() && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(this.email().trim()));
}
Interactive playground

Change the settings and try the result.

Device captures shown in English.

Form Field · android · native capture
AndroidNative screenshot
Form Field · ios · native capture
iOSNative screenshot

Personalization

Projected content

Between the field label and its hint or error. Project the actual input control and give it the same accessible label; FormField supplies layout, not a form value.

Use native elements from @ng-native/components and public Neural Native controls. Angular styles belong to the component that declares this content.

API reference

Inputs

NameTypeDefaultBindingDescription
labelstringRequiredInputVisible label above the projected control. Set the inner control’s accessibilityLabel explicitly; the wrapper does not create or label a control automatically.
requiredbooleanfalseInputAdds an asterisk to the visible label. It does not validate, block editing or require a value in the inner control.
invalidbooleanfalseInputShows error instead of hint when an error message is provided. Bind the validation state to the inner control separately to style its border.
errorstring''InputApplication-provided error message, displayed only when invalid is true and this string is nonempty. FormField does not calculate validation rules.
hintstring''InputHelp text below the projected content, shown when no active error message replaces it.

Models

This component declares no two-way models.

Outputs

This component declares no public outputs.