diff --git a/adev-es/src/app/routing/sub-navigation-data.ts b/adev-es/src/app/routing/sub-navigation-data.ts index 9fe4a39..3092f60 100644 --- a/adev-es/src/app/routing/sub-navigation-data.ts +++ b/adev-es/src/app/routing/sub-navigation-data.ts @@ -66,7 +66,7 @@ const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [ contentPath: 'introduction/essentials/templates', }, { - label: 'Forms with signals', + label: 'Formularios con signals', path: 'essentials/signal-forms', contentPath: 'introduction/essentials/signal-forms', status: 'new', diff --git a/adev-es/src/content/introduction/essentials/signal-forms.en.md b/adev-es/src/content/introduction/essentials/signal-forms.en.md new file mode 100644 index 0000000..1ad8123 --- /dev/null +++ b/adev-es/src/content/introduction/essentials/signal-forms.en.md @@ -0,0 +1,271 @@ + + +IMPORTANT: Signal Forms are [experimental](/reference/releases#experimental). The API may change in future releases. Avoid using experimental APIs in production applications without understanding the risks. + +Signal Forms manage form state using Angular signals to provide automatic synchronization between your data model and the UI with Angular Signals. + +This guide walks you through the core concepts to create forms with Signal Forms. Here's how it works: + +## Creating your first form + +### 1. Create a form model with `signal()` + +Every form starts by creating a signal that holds your form's data model: + +```ts +interface LoginData { + email: string; + password: string; +} + +const loginModel = signal({ + email: '', + password: '', +}); +``` + +### 2. Pass the form model to `form()` to create a `FieldTree` + +Then, you pass your form model into the `form()` function to create a **field tree** - an object structure that mirrors your model's shape, allowing you to access fields with dot notation: + +```ts +const loginForm = form(loginModel); + +// Access fields directly by property name +loginForm.email +loginForm.password +``` + +### 3. Bind HTML inputs with `[field]` directive + +Next, you bind your HTML inputs to the form using the `[field]` directive, which creates two-way binding between them: + +```html + + +``` + +As a result, user changes (such as typing in the field) automatically updates the form. + +NOTE: The `[field]` directive also syncs field state for attributes like `required`, `disabled`, and `readonly` when appropriate. + +### 4. Read field values with `value()` + +You can access field state by calling the field as a function. This returns a `FieldState` object containing reactive signals for the field's value, validation status, and interaction state: + +```ts +loginForm.email() // Returns FieldState with value(), valid(), touched(), etc. +``` + +To read the field's current value, access the `value()` signal: + +```html + +

Email: {{ loginForm.email().value() }}

+``` + +```ts +// Get the current value +const currentEmail = loginForm.email().value(); +``` + +### 5. Update field values with `set()` + +You can programmatically update a field's value using the `value.set()` method. This updates both the field and the underlying model signal: + +```ts +// Update the value programmatically +loginForm.email().value.set('alice@wonderland.com'); +``` + +As a result, both the field value and the model signal are updated automatically: + +```ts +// The model signal is also updated +console.log(loginModel().email); // 'alice@wonderland.com' +``` + +Here's a complete example: + + + + + + + +## Basic usage + +The `[field]` directive works with all standard HTML input types. Here are the most common patterns: + +### Text inputs + +Text inputs work with various `type` attributes and textareas: + +```html + + + +``` + +#### Numbers + +Number inputs automatically convert between strings and numbers: + +```html + + +``` + +#### Date and time + +Date inputs store values as `YYYY-MM-DD` strings, and time inputs use `HH:mm` format: + +```html + + + +``` + +If you need to convert date strings to Date objects, you can do so by passing the field value into `Date()`: + +```ts +const dateObject = new Date(form.eventDate().value()); +``` + +#### Multiline text + +Textareas work the same way as text inputs: + +```html + + +``` + +### Checkboxes + +Checkboxes bind to boolean values: + +```html + + +``` + +#### Multiple checkboxes + +For multiple options, create a separate boolean `field` for each: + +```html + + +``` + +### Radio buttons + +Radio buttons work similarly to checkboxes. As long as the radio buttons use the same `[field]` value, Signal Forms will automatically bind the same `name` attribute to all of them: + +```html + + +``` + +When a user selects a radio button, the form `field` stores the value from that radio button's `value` attribute. For example, selecting "Premium" sets `form.plan().value()` to `"premium"`. + +### Select dropdowns + +Select elements work with both static and dynamic options: + +```html + + + + + +``` + +NOTE: Multiple select (` ``` -As a result, user changes (such as typing in the field) automatically updates the form. +Como resultado, los cambios del usuario (como escribir en el campo) actualizan automáticamente el formulario. -NOTE: The `[field]` directive also syncs field state for attributes like `required`, `disabled`, and `readonly` when appropriate. +NOTA: La directiva `[field]` también sincroniza el estado del campo para atributos como `required`, `disabled` y `readonly` cuando corresponde. -### 4. Read field values with `value()` +### 4. Lee valores de campo con `value()` -You can access field state by calling the field as a function. This returns a `FieldState` object containing reactive signals for the field's value, validation status, and interaction state: +Puedes acceder al estado del campo llamando al campo como una función. Esto devuelve un objeto `FieldState` que contiene signals reactivos para el valor del campo, estado de validación y estado de interacción: ```ts -loginForm.email() // Returns FieldState with value(), valid(), touched(), etc. +loginForm.email() // Devuelve FieldState con value(), valid(), touched(), etc. ``` -To read the field's current value, access the `value()` signal: +Para leer el valor actual del campo, accede al signal `value()`: ```html - +

Email: {{ loginForm.email().value() }}

``` ```ts -// Get the current value +// Obtiene el valor actual const currentEmail = loginForm.email().value(); ``` -### 5. Update field values with `set()` +### 5. Actualiza valores de campo con `set()` -You can programmatically update a field's value using the `value.set()` method. This updates both the field and the underlying model signal: +Puedes actualizar programáticamente el valor de un campo usando el método `value.set()`. Esto actualiza tanto el campo como el signal del modelo subyacente: ```ts -// Update the value programmatically +// Actualiza el valor programáticamente loginForm.email().value.set('alice@wonderland.com'); ``` -As a result, both the field value and the model signal are updated automatically: +Como resultado, tanto el valor del campo como el signal del modelo se actualizan automáticamente: ```ts -// The model signal is also updated +// El signal del modelo también se actualiza console.log(loginModel().email); // 'alice@wonderland.com' ``` -Here's a complete example: +Aquí tienes un ejemplo completo: @@ -93,48 +93,48 @@ Here's a complete example: -## Basic usage +## Uso básico -The `[field]` directive works with all standard HTML input types. Here are the most common patterns: +La directiva `[field]` funciona con todos los tipos de input HTML estándar. Aquí están los patrones más comunes: -### Text inputs +### Inputs de texto -Text inputs work with various `type` attributes and textareas: +Los inputs de texto funcionan con varios atributos `type` y textareas: ```html - + ``` -#### Numbers +#### Números -Number inputs automatically convert between strings and numbers: +Los inputs numéricos convierten automáticamente entre strings y números: ```html - + ``` -#### Date and time +#### Fecha y hora -Date inputs store values as `YYYY-MM-DD` strings, and time inputs use `HH:mm` format: +Los inputs de fecha almacenan valores como strings `YYYY-MM-DD`, y los inputs de hora usan formato `HH:mm`: ```html - + ``` -If you need to convert date strings to Date objects, you can do so by passing the field value into `Date()`: +Si necesitas convertir strings de fecha a objetos Date, puedes hacerlo pasando el valor del campo a `Date()`: ```ts const dateObject = new Date(form.eventDate().value()); ``` -#### Multiline text +#### Texto multilínea -Textareas work the same way as text inputs: +Los textareas funcionan de la misma manera que los inputs de texto: ```html @@ -143,39 +143,39 @@ Textareas work the same way as text inputs: ### Checkboxes -Checkboxes bind to boolean values: +Los checkboxes se vinculan a valores booleanos: ```html - + ``` -#### Multiple checkboxes +#### Múltiples checkboxes -For multiple options, create a separate boolean `field` for each: +Para múltiples opciones, crea un `field` booleano separado para cada una: ```html ``` -### Radio buttons +### Botones de radio -Radio buttons work similarly to checkboxes. As long as the radio buttons use the same `[field]` value, Signal Forms will automatically bind the same `name` attribute to all of them: +Los botones de radio funcionan de manera similar a los checkboxes. Mientras los botones de radio usen el mismo valor `[field]`, Signal Forms vinculará automáticamente el mismo atributo `name` a todos ellos: ```html ``` -When a user selects a radio button, the form `field` stores the value from that radio button's `value` attribute. For example, selecting "Premium" sets `form.plan().value()` to `"premium"`. +Cuando un usuario selecciona un botón de radio, el `field` del formulario almacena el valor del atributo `value` de ese botón de radio. Por ejemplo, seleccionar "Premium" establece `form.plan().value()` a `"premium"`. -### Select dropdowns +### Menús desplegables select -Select elements work with both static and dynamic options: +Los elementos select funcionan con opciones tanto estáticas como dinámicas: ```html - + - + ``` -NOTE: Multiple select (``) no está soportado por la directiva `[field]` en este momento. -## Validation and state +## Validación y estado -Signal Forms provides built-in validators that you can apply to your form fields. To add validation, pass a schema function as the second argument to `form()`: +Signal Forms proporciona validadores integrados que puedes aplicar a los campos de tu formulario. Para agregar validación, pasa una función de esquema como segundo argumento a `form()`: ```ts const loginForm = form(loginModel, (schemaPath) => { @@ -220,26 +220,26 @@ const loginForm = form(loginModel, (schemaPath) => { }); ``` -The schema function receives a **schema path** parameter that provides paths to your fields for configuring validation rules. +La función de esquema recibe un parámetro **schema path** que proporciona rutas a tus campos para configurar reglas de validación. -Common validators include: +Los validadores comunes incluyen: -- **`required()`** - Ensures the field has a value -- **`email()`** - Validates email format -- **`min()`** / **`max()`** - Validates number ranges -- **`minLength()`** / **`maxLength()`** - Validates string or collection length -- **`pattern()`** - Validates against a regex pattern +- **`required()`** - Asegura que el campo tenga un valor +- **`email()`** - Valida formato de email +- **`min()`** / **`max()`** - Valida rangos numéricos +- **`minLength()`** / **`maxLength()`** - Valida longitud de string o colección +- **`pattern()`** - Valida contra un patrón regex -You can also customize error messages by passing an options object as the second argument to the validator: +También puedes personalizar mensajes de error pasando un objeto de opciones como segundo argumento al validador: ```ts -required(schemaPath.email, { message: 'Email is required' }); -email(schemaPath.email, { message: 'Please enter a valid email address' }); +required(schemaPath.email, { message: 'El email es requerido' }); +email(schemaPath.email, { message: 'Por favor ingresa un email válido' }); ``` -Each form field exposes its validation state through signals. For example, you can check `field().valid()` to see if validation passes, `field().touched()` to see if the user has interacted with it, and `field().errors()` to get the list of validation errors. +Cada campo de formulario expone su estado de validación a través de signals. Por ejemplo, puedes verificar `field().valid()` para ver si la validación pasa, `field().touched()` para ver si el usuario ha interactuado con él, y `field().errors()` para obtener la lista de errores de validación. -Here's a complete example: +Aquí tienes un ejemplo completo: @@ -247,25 +247,25 @@ Here's a complete example: -### Field State Signals +### Signals de Estado de Campo -Every `field()` provides these state signals: +Cada `field()` proporciona estos signals de estado: -| State | Description | -| ------------ | -------------------------------------------------------------------------- | -| `valid()` | Returns `true` if the field passes all validation rules | -| `touched()` | Returns `true` if the user has focused and blurred the field | -| `dirty()` | Returns `true` if the user has changed the value | -| `disabled()` | Returns `true` if the field is disabled | -| `readonly()` | Returns `true` if the field is readonly | -| `pending()` | Returns `true` if async validation is in progress | -| `errors()` | Returns an array of validation errors with `kind` and `message` properties | +| Estado | Descripción | +| ------------ | ------------------------------------------------------------------------------- | +| `valid()` | Devuelve `true` si el campo pasa todas las reglas de validación | +| `touched()` | Devuelve `true` si el usuario ha enfocado y desenfocado el campo | +| `dirty()` | Devuelve `true` si el usuario ha cambiado el valor | +| `disabled()` | Devuelve `true` si el campo está deshabilitado | +| `readonly()` | Devuelve `true` si el campo es de solo lectura | +| `pending()` | Devuelve `true` si la validación asíncrona está en progreso | +| `errors()` | Devuelve un array de errores de validación con propiedades `kind` y `message` | -## Next steps +## Siguientes pasos -To learn more about Signal Forms and how it works, check out the in-depth guides: +Para aprender más sobre Signal Forms y cómo funciona, consulta las guías detalladas: -- [Overview](guide/forms/signals/overview) - Introduction to Signal Forms and when to use them -- [Form models](guide/forms/signals/models) - Creating and managing form data with signals -- [Field state management](guide/forms/signals/field-state-management) - Working with validation state, interaction tracking, and field visibility -- [Validation](guide/forms/signals/validation) - Built-in validators, custom validation rules, and async validation +- [Visión general](guide/forms/signals/overview) - Introducción a Signal Forms y cuándo usarlos +- [Modelos de formulario](guide/forms/signals/models) - Creando y gestionando datos de formularios con signals +- [Gestión de estado de campo](guide/forms/signals/field-state-management) - Trabajando con estado de validación, seguimiento de interacción y visibilidad de campos +- [Validación](guide/forms/signals/validation) - Validadores integrados, reglas de validación personalizadas y validación asíncrona