feat(web): dirección del documento desde AddressExtension (texto y corrección con «…») y campos de lista que muestran el código con formato (cuenta asociada)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c1f2cea1e1
commit
896fa25f2f
9 files changed
+342
-14
No files matched your search
@@ -4,6 +4,7 @@ import {
|
||||
booleanAttribute,
|
||||
computed,
|
||||
Injector,
|
||||
effect,
|
||||
inject,
|
||||
input,
|
||||
model,
|
||||
@@ -37,7 +38,8 @@ import { SboField } from './sbo-field';
|
||||
>
|
||||
<sbo-input
|
||||
#box
|
||||
[(value)]="value"
|
||||
[value]="shown()"
|
||||
(valueChange)="typing($event)"
|
||||
[readonly]="readOnly()"
|
||||
[disabled]="disabled()"
|
||||
[required]="required()"
|
||||
@@ -93,6 +95,36 @@ export class LookupField extends FieldBase {
|
||||
private resolved = '';
|
||||
private readonly box = viewChild.required<TextInput>('box');
|
||||
|
||||
/** El usuario está escribiendo: se muestra lo que escribe y no el texto con que la lista presenta el código guardado. */
|
||||
private readonly editing = signal(false);
|
||||
/**
|
||||
* Lo que se ve en el campo: el código guardado o, en una lista que tiene texto propio para él (la cuenta con su
|
||||
* código con formato en vez del interno `_SYS…`), ese texto.
|
||||
*/
|
||||
protected readonly shown = computed(() => {
|
||||
const v = this.value();
|
||||
const codes = this.lookup().codes;
|
||||
return !this.editing() && codes && v !== '' ? codes.display(v) : v;
|
||||
});
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
effect(() => {
|
||||
const v = this.value();
|
||||
const codes = this.lookup().codes;
|
||||
// un valor que llega de fuera (documento cargado, valor por defecto) ya está resuelto y se pide su texto; lo que se escribe, no
|
||||
if (!this.editing()) {
|
||||
if (codes && v !== '') codes.ensure([v]);
|
||||
this.resolved = v.trim();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected typing(text: string): void {
|
||||
this.editing.set(true);
|
||||
this.value.set(text);
|
||||
}
|
||||
|
||||
protected openList(): void {
|
||||
if (!this.readOnly() && !this.disabled()) this.listOpen.set(true);
|
||||
}
|
||||
@@ -111,6 +143,8 @@ export class LookupField extends FieldBase {
|
||||
private apply(row: VhRow): void {
|
||||
const key = this.lookup().valueKey ?? this.lookup().columns[0]?.key ?? '';
|
||||
this.missing.set(null);
|
||||
this.lookup().codes?.remember(row);
|
||||
this.editing.set(false);
|
||||
this.value.set(String(row[key] ?? ''));
|
||||
this.resolved = this.value();
|
||||
this.picked.emit(row);
|
||||
@@ -118,13 +152,21 @@ export class LookupField extends FieldBase {
|
||||
|
||||
protected async resolveTyped(): Promise<void> {
|
||||
const code = this.value().trim();
|
||||
if (!this.resolveOnLeave() || this.readOnly() || this.disabled() || this.listOpen()) return;
|
||||
if (!this.editing()) return; // no se escribió nada: lo guardado ya está resuelto
|
||||
if (!this.resolveOnLeave() || this.readOnly() || this.disabled() || this.listOpen()) {
|
||||
this.editing.set(false);
|
||||
return;
|
||||
}
|
||||
if (!code) {
|
||||
this.missing.set(null);
|
||||
this.resolved = '';
|
||||
this.editing.set(false);
|
||||
return;
|
||||
}
|
||||
if (code === this.resolved) {
|
||||
this.editing.set(false);
|
||||
return;
|
||||
}
|
||||
if (code === this.resolved) return;
|
||||
try {
|
||||
const row = await this.injector.get(SlLookupApi).find(this.lookup(), code);
|
||||
if (this.value().trim() !== code) return; // el usuario siguió escribiendo
|
||||
@@ -132,6 +174,8 @@ export class LookupField extends FieldBase {
|
||||
else this.missing.set({ code, text: `No existe «${code}» en ${this.lookup().title.toLowerCase()}.` });
|
||||
} catch {
|
||||
this.missing.set({ code, text: 'No se pudo comprobar el código.' });
|
||||
} finally {
|
||||
if (this.value().trim() === code) this.editing.set(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user