Formularios
Form Field
Un contenedor para la etiqueta, la ayuda y los errores del control personalizado que colocas dentro.
Importación
import { NeuFormFieldComponent } from '@neural-ui/native/form-field';Ejemplos
Importa ExampleComponent en su padre y coloca <app-example /> dentro del neu-theme raíz de tu aplicación. El preview aporta el marco y las zonas seguras; utiliza la estructura raíz de Instalación en tu app.
Invita a tu próximo compañero
Escribe y valida el correo de invitación. El contenedor rodea un TextInput real proyectado con etiqueta, ayuda y error; no crea un segundo input.
Ver y copiar el ejemplo completo
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">Invita a tu próximo compañero</text><text class="product-caption">Una etiqueta clara, ayuda útil y errores que se pueden resolver</text></view><view class="product-surface"><neu-form-field #emailField label="Dirección de correo" hint="Utilizaremos esta dirección para las invitaciones" [required]="true" [invalid]="invalid()" error="Introduce una dirección de correo válida.">
<text-input class="projected-control" [class.invalid]="invalid()"
accessibilityLabel="Dirección de correo (obligatorio)"
[accessibilityLabelledBy]="emailField.labelId"
[accessibilityHint]="invalid() ? 'Introduce una dirección de correo válida.' : 'Utilizaremos esta dirección para las invitaciones'"
keyboardType="email-address" autoCapitalize="none" [autoCorrect]="false"
[invalid]="invalid()" [touched]="attempted()" [(value)]="email" />
</neu-form-field>
<view class="field-actions">
<neu-button label="Comprobar correo" 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()));
}Ajusta la configuración y prueba el resultado.
Capturas del dispositivo en inglés.


Personalización
Contenido proyectado
Entre la etiqueta del campo y su ayuda o error. Proyecta el control de entrada real y dale el mismo nombre accesible; FormField aporta la estructura, no el valor del formulario.
Utiliza elementos nativos de @ng-native/components y controles públicos de Neural Native. Los estilos Angular pertenecen al componente que declara este contenido.
Referencia API
Inputs
| Nombre | Tipo | Predeterminado | Enlace | Descripción |
|---|---|---|---|---|
| label | string | Obligatorio | Input | Etiqueta visible sobre el control proyectado. Define expresamente accessibilityLabel en el control interior; el contenedor no crea ni etiqueta automáticamente un control. |
| required | boolean | false | Input | Añade un asterisco a la etiqueta visible. No valida, no bloquea la edición ni exige un valor en el control interior. |
| invalid | boolean | false | Input | Muestra error en lugar de hint si se ha proporcionado un mensaje de error. Enlaza el estado de validación también al control interior para cambiar su borde. |
| error | string | '' | Input | Mensaje de error aportado por la aplicación; aparece solo cuando invalid es true y este string no está vacío. FormField no calcula reglas de validación. |
| hint | string | '' | Input | Ayuda debajo del contenido proyectado; se muestra mientras no la sustituya un mensaje de error activo. |
Models
Este componente no declara models bidireccionales.
Outputs
Este componente no declara outputs públicos.