<aoc-from>
#Este componente se usa para mostrar un formulario, es decir, para la creación y edición de modelos.
A nivel visual, los formularios se colocan dentro de ventanas, aunque esto es transparente para el programador.
Nombre | Tipo | Descripción |
---|---|---|
modelConfig | AocModelConfig | La instancia model-config que se usará internamente |
formGroup | FormGroup | El FormGroup asociado al formulario |
restOptions | AocRestOptions | Las opciones de carga para la api rest |
saveButtonWithTypeSubmit | boolean (default: false) | Útil para formularios que quieres enviar al pulsar la tecla enter |
newModelTitle | string, Observable, Promise, function | Proveer el título de la ventana del formulario al crear un nuevo modelo |
editModelTitle | string, Observable, Promise, function | Proveer el título de la ventana del formulario al editar un nuevo modelo |
saveModel | 'persist' o 'persistWithTask' | El modo persist no cierra la ventana hasta que el servidor ha respondido (por defecto), el modo persistWithTask realiza la acción en segundo plano para evitar timeouts en la llamada xhr |
Nombre | Tipo | Descripción |
---|---|---|
aocDynFormGroup | AocDynFormGroup | Emite la configuración de formulario dinámica |
Nota: AocDynFormGroup es una configuración que permite establecer valores o estados a un control en un momento dado, incluso crear el control si es necesario. Al abrir una ventana de formulario, se le puede enviar dicha información, como por ejemplo sería establecer un valor para una dependencia (de otro modelo).
Un formulario con un campo de texto (Name). El componente aoc-form
debe estructurarse de la siguiente forma.
El template body
y los elementos aoc-ui-form-page
y aoc-ui-form-row
son necesarios.
<aoc-form [formGroup]="formGroup" [modelConfig]="modelConfig">
<ng-template aocFormTemplate="body">
<aoc-ui-form-page>
<aoc-ui-form-row>
<input aocUiInputText aocUiFormField="Name" [formControlName]="StoreClass.field.NAME">
</aoc-ui-form-row>
</aoc-ui-form-page>
</ng-template>
</aoc-form>
El atributo StoreClass
hace referencia al modelo Store
y se usa para para enlazar los campos
del modelo con el formulario a través del formControlName
.
export default class StoreFormComponent {
protected StoreClass = Store;
protected modelConfig = inject(StoreModelConfig);
protected formGroup = new FormGroup<AocFormGroupType<Store>>({
name: new FormControl(null, Validators.required)
});
}
Vea el ejemplo completo en quest-client/src/app/features/schemas/items/store/store-form.component.ts
Este es un ejemplo de un formulario con pestañas (tiene 3 pestañas: Data, Contact, Files), con agrupaciones de campos, subformularios y subcomponentes.
<aoc-form [modelConfig]="modelConfig" [formGroup]="formGroup" [restOptions]="restOptions">
<ng-template aocFormTemplate="body">
<aoc-ui-tab-panel>
<aoc-ui-tab-panel-content header="Data">
<aoc-ui-form-page>
<aoc-ui-form-row>
<input aocUiInputText aocUiFormField="Code" [formControlName]="CustomerClass.field.CODE" placeholder="Autogenerated on server if empty...">
<app-language-autocomplete aocUiFormField="Language" [formControlName]="CustomerClass.entity.LANGUAGE"></app-language-autocomplete>
<app-gender-autocomplete aocUiFormField="Gender" [formControlName]="CustomerClass.entity.GENDER"></app-gender-autocomplete>
</aoc-ui-form-row>
<app-legal-data-template-subform [formGroupName]="CustomerClass.embedded.LEGAL_DATA_TEMPLATE"></app-legal-data-template-subform>
<aoc-ui-form-row>
<input aocUiInputText aocUiFormField="Trade name" [span]="18" [formControlName]="CustomerClass.field.TRADE_NAME" placeholder="Just for companies, not mandatory...">
<aoc-ui-datetime-picker aocUiFormField="Birthdate" [formControlName]="CustomerClass.field.BIRTHDATE" mode="date" placeholder="mm/dd/y"></aoc-ui-datetime-picker>
</aoc-ui-form-row>
<app-address-template-subform [formGroupName]="CustomerClass.embedded.ADDRESS_TEMPLATE"></app-address-template-subform>
</aoc-ui-form-page>
</aoc-ui-tab-panel-content>
<aoc-ui-tab-panel-content header="Contact">
<aoc-ui-form-page>
<aoc-ui-form-fieldset title="Main Contact Info">
<app-contact-template-subform></app-contact-template-subform>
</aoc-ui-form-fieldset>
<aoc-ui-form-row aocUiFormRowHeight="stretch">
<app-contact-grid-field aocUiFormField="Additional Contacts" [formControlName]="CustomerClass.collection.CONTACT"></app-contact-grid-field>
</aoc-ui-form-row>
</aoc-ui-form-page>
</aoc-ui-tab-panel-content>
<aoc-ui-tab-panel-content header="Files">
<aoc-ui-form-page>
<aoc-ui-form-row aocUiFormRowHeight="stretch">
<app-file-grid-field
aocUiFormField="Customer files (documents, contracts...)"
[formControlName]="CustomerClass.collection.FILE"
[fileParentClass]="CustomerClass"
fileDirectory="Customers"
></app-file-grid-field>
</aoc-ui-form-row>
</aoc-ui-form-page>
</aoc-ui-tab-panel-content>
</aoc-ui-tab-panel>
</ng-template>
</aoc-form>
En la definición del formGroup
tenemos ejemplos de validadores, campos embedidos (subobjeto), campos inline (campos al mismo nivel), y colecciones (relaciones en PostgreSQL).
Tanto los campos embedidos como los campos inline podrían expresarse como herencias en PostgreSQL.
Las restOptions
indican que se deben cargar ciertas relaciones para que el formulario pueda mostrar los datos correctamente (por ejemplo, el editar).
this.formGroup = new FormGroup<AocFormGroupType<Customer>>({
code: new FormControl(null, AocUiValidators.positiveNumber(0)),
trade_name: new FormControl(null),
birthdate: new FormControl(null),
gender: new FormControl(this.questDefaultsService.gender),
language: new FormControl(this.questDefaultsService.language, Validators.required),
legalDataTemplate: this.questUtilsService.addControlsForLegalDataTemplate(), // Embedded
addressTemplate: this.questUtilsService.addControlsForAddressTemplate(), // Embedded
contactCollection: new FormControl([]),
fileCollection: new FormControl([])
});
// Inline
this.questUtilsService.addControlsForContactTemplate(this.formGroup);
this.restOptions = {
populate: {
language: true,
gender: true,
contactCollection: true,
fileCollection: true
}
}
Ejemplo completo en quest-client/src/app/features/schemas/customers/customer/customer-form.component.ts
Definición completa en la API.
<aoc-subform>
#Este componente se utiliza para subformularios (formularios dentro de formularios).
En el ejemplo avanzado, se usaría en <app-legal-data-template-subform>
.
El template recibe el formGroup
por contexto automáticamente y, en este caso, lo asignamos a la directiva formGroup
de
la nueva row en cuestión aoc-ui-form-row
que añadimos al formulario padre.
<aoc-subform>
<ng-template let-formGroup>
<aoc-ui-form-row [formGroup]="formGroup">
<input aocUiInputText aocUiFormField="Legal name" [formControlName]="LegalDataTemplateClass.field.LEGAL_NAME">
<input [span]="6" aocUiInputText aocUiFormField="Document number" [formControlName]="LegalDataTemplateClass.field.DOCUMENT_NUMBER">
<app-identity-document-type-autocomplete
[span]="6"
aocUiFormField="Identity document type"
[formControlName]="LegalDataTemplateClass.entity.IDENTITY_DOCUMENT_TYPE"
></app-identity-document-type-autocomplete>
</aoc-ui-form-row>
</ng-template>
</aoc-subform>
El modelo LegalDataTemplate
es un AocEmbeddedModel
que no es más que un modelo normal con algunas simplificaciones (echa un ojo a mikro-orm.
protected LegalDataTemplateClass = LegalDataTemplate;
Definición completa en la API.
AocFormController
#En los formularios siempre hay que proveer AocFormController
. Esta clase funciona como herramienta
de control del ciclo de vida de los formularios y nos permite engancharnos a hooks, entre otras funcionalidades.
Además, siempre podremos inyectarla también en componentes que estén dentro de la misma jerarquía de nuestro formulario padre.
providers: [ AocFormController ]
Por ejemplo, recargamos el navegador cuando hemos pulsado en el botón Guardar de un formulario y se ha guardado correctamente el modelo. El modelo se recibe como parámetro.
this.aocFormController.addAfterSaveAction(_ => {
window.location.reload();
});
Definición completa en la API.
Por favor, busque en Issues y Discussions en Github para más información