@praxisui/dynamic-fields 9.0.0-rc.3 → 9.0.0-rc.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ai/component-registry.json +2 -2
- package/docs/dynamic-fields-field-selection-guide.md +2 -0
- package/fesm2022/praxisui-dynamic-fields.mjs +41 -3
- package/package.json +3 -3
- package/src/lib/components/material-async-select/pdx-material-async-select.json-api.md +2 -0
- package/types/praxisui-dynamic-fields.d.ts +3 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "1.0.0",
|
|
3
|
-
"generatedAt": "2026-07-
|
|
3
|
+
"generatedAt": "2026-07-26T09:12:02.628Z",
|
|
4
4
|
"packageName": "@praxisui/dynamic-fields",
|
|
5
|
-
"packageVersion": "9.0.0-rc.
|
|
5
|
+
"packageVersion": "9.0.0-rc.5",
|
|
6
6
|
"sourceRegistry": "praxis-component-registry-ingestion",
|
|
7
7
|
"sourceRegistryVersion": "1.0.0",
|
|
8
8
|
"componentCount": 76,
|
|
@@ -149,6 +149,8 @@ Checklist minimo para promocao:
|
|
|
149
149
|
- o recurso oferece busca paginada e reidratacao por ids (`filter` e `byIds`) para valores salvos;
|
|
150
150
|
- `selectionPolicy` documenta status, elegibilidade e preservacao de valor historico quando aplicavel;
|
|
151
151
|
- dependencias entre entidades usam `dependsOn` e `dependencyFilterMap`, sem inferencia por nome de campo no Angular;
|
|
152
|
+
- ao mudar uma dependencia canonica, o runtime limpa por padrao a selecao dependente, emite a alteracao para continuar a cascata e preserva apenas o valor hidratado na montagem inicial;
|
|
153
|
+
- use `selectionPolicy.allowRetainInvalidExistingValue=true` somente quando o dominio permitir manter explicitamente uma selecao historica fora do novo conjunto de opcoes;
|
|
152
154
|
- surfaces de detalhe sao publicadas pelo recurso quando `navigateToDetail` estiver habilitado;
|
|
153
155
|
- existe demo jogavel cobrindo campo de formulario e, quando o uso for filtro, `inlineEntityLookup`;
|
|
154
156
|
- existe teste focal ou e2e cobrindo busca, selecao, reidratacao e estado bloqueado/historico;
|
|
@@ -4340,15 +4340,21 @@ class SimpleBaseSelectComponent extends SimpleBaseInputComponent {
|
|
|
4340
4340
|
const debounceMs = Number(meta.dependencyDebounceMs ?? this.global.getDynamicFields()?.cascade?.debounceMs ?? 150);
|
|
4341
4341
|
const mergeStrategy = meta.dependencyMergeStrategy ?? 'merge';
|
|
4342
4342
|
const loadOnChange = meta.dependencyLoadOnChange ?? this.global.getDynamicFields()?.cascade?.loadOnChange ?? 'respectLoadOn';
|
|
4343
|
+
let dependencySnapshotInitialized = false;
|
|
4343
4344
|
// Subscribe to combined changes
|
|
4344
4345
|
this.dependencySub = combineLatest(streams)
|
|
4345
4346
|
.pipe(debounceTime(debounceMs))
|
|
4346
4347
|
.subscribe((values) => {
|
|
4347
4348
|
const availableControls = controls.filter((entry) => !!entry.control);
|
|
4348
4349
|
const fragment = this.applyDependencyValues(meta, availableControls, values);
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
|
|
4350
|
+
const isInitialDependencySnapshot = !dependencySnapshotInitialized;
|
|
4351
|
+
dependencySnapshotInitialized = true;
|
|
4352
|
+
if (!isInitialDependencySnapshot &&
|
|
4353
|
+
this.shouldResetOnDependencyChange(meta) &&
|
|
4354
|
+
this.hasMeaningfulSelectValue(this.control().value)) {
|
|
4355
|
+
const emptyValue = this.multiple() ? [] : null;
|
|
4356
|
+
this.setValue(emptyValue, { emitEvent: true });
|
|
4357
|
+
this.control().markAsDirty();
|
|
4352
4358
|
}
|
|
4353
4359
|
// Trigger reload according to strategy
|
|
4354
4360
|
if (!this.resourcePath())
|
|
@@ -4375,6 +4381,21 @@ class SimpleBaseSelectComponent extends SimpleBaseInputComponent {
|
|
|
4375
4381
|
});
|
|
4376
4382
|
});
|
|
4377
4383
|
}
|
|
4384
|
+
shouldResetOnDependencyChange(meta) {
|
|
4385
|
+
if (meta.resetOnDependentChange !== undefined) {
|
|
4386
|
+
return meta.resetOnDependentChange === true;
|
|
4387
|
+
}
|
|
4388
|
+
const hasCanonicalDependencies = Array.isArray(meta.optionSource?.dependsOn) &&
|
|
4389
|
+
meta.optionSource.dependsOn.length > 0;
|
|
4390
|
+
const retainsInvalidExistingValue = meta.optionSource?.selectionPolicy?.allowRetainInvalidExistingValue === true;
|
|
4391
|
+
return hasCanonicalDependencies && !retainsInvalidExistingValue;
|
|
4392
|
+
}
|
|
4393
|
+
hasMeaningfulSelectValue(value) {
|
|
4394
|
+
if (Array.isArray(value)) {
|
|
4395
|
+
return value.length > 0;
|
|
4396
|
+
}
|
|
4397
|
+
return value !== null && value !== undefined && value !== '';
|
|
4398
|
+
}
|
|
4378
4399
|
extractDependencyValue(raw, path) {
|
|
4379
4400
|
if (raw == null)
|
|
4380
4401
|
return raw;
|
|
@@ -25336,6 +25357,20 @@ class MaterialCpfCnpjInputComponent extends SimpleBaseInputComponent {
|
|
|
25336
25357
|
const formatted = this.formatValue(stringValue);
|
|
25337
25358
|
super.writeValue(formatted);
|
|
25338
25359
|
}
|
|
25360
|
+
applyNativeDisplayMask(value = this.control().value) {
|
|
25361
|
+
const input = this.nativeElement;
|
|
25362
|
+
if (!input || input.tagName.toLowerCase() !== 'input') {
|
|
25363
|
+
return;
|
|
25364
|
+
}
|
|
25365
|
+
const formatted = this.formatValue(typeof value === 'string'
|
|
25366
|
+
? value
|
|
25367
|
+
: value == null
|
|
25368
|
+
? null
|
|
25369
|
+
: String(value));
|
|
25370
|
+
if (input.value !== formatted) {
|
|
25371
|
+
input.value = formatted;
|
|
25372
|
+
}
|
|
25373
|
+
}
|
|
25339
25374
|
handleInput(event) {
|
|
25340
25375
|
const input = event.target;
|
|
25341
25376
|
const value = input.value;
|
|
@@ -64029,6 +64064,7 @@ const DYNAMIC_FIELDS_PLAYGROUND_CATALOG = [
|
|
|
64029
64064
|
metadataPatch: {
|
|
64030
64065
|
documentType: 'cpf',
|
|
64031
64066
|
version: 'legacy',
|
|
64067
|
+
validators: { cpfCnpj: true },
|
|
64032
64068
|
},
|
|
64033
64069
|
initialValue: '529.982.247-25',
|
|
64034
64070
|
},
|
|
@@ -64039,6 +64075,7 @@ const DYNAMIC_FIELDS_PLAYGROUND_CATALOG = [
|
|
|
64039
64075
|
metadataPatch: {
|
|
64040
64076
|
documentType: 'cnpj',
|
|
64041
64077
|
version: 'legacy',
|
|
64078
|
+
validators: { cpfCnpj: true },
|
|
64042
64079
|
},
|
|
64043
64080
|
initialValue: '11.444.777/0001-61',
|
|
64044
64081
|
},
|
|
@@ -64049,6 +64086,7 @@ const DYNAMIC_FIELDS_PLAYGROUND_CATALOG = [
|
|
|
64049
64086
|
metadataPatch: {
|
|
64050
64087
|
documentType: 'cnpj',
|
|
64051
64088
|
version: 'alpha',
|
|
64089
|
+
validators: { cpfCnpj: true },
|
|
64052
64090
|
},
|
|
64053
64091
|
initialValue: '12.ABC.345/01DE-35',
|
|
64054
64092
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@praxisui/dynamic-fields",
|
|
3
|
-
"version": "9.0.0-rc.
|
|
3
|
+
"version": "9.0.0-rc.5",
|
|
4
4
|
"description": "Angular Material-based dynamic form fields for Praxis UI with lazy loading and metadata-driven rendering.",
|
|
5
5
|
"peerDependencies": {
|
|
6
6
|
"@angular/common": "^21.0.0",
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
"@angular/platform-browser": "^21.0.0",
|
|
12
12
|
"@angular/router": "^21.0.0",
|
|
13
13
|
"rxjs": "^7.8.0",
|
|
14
|
-
"@praxisui/core": "^9.0.0-rc.
|
|
15
|
-
"@praxisui/cron-builder": "^9.0.0-rc.
|
|
14
|
+
"@praxisui/core": "^9.0.0-rc.5",
|
|
15
|
+
"@praxisui/cron-builder": "^9.0.0-rc.5"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"libphonenumber-js": "^1.12.41",
|
|
@@ -416,6 +416,8 @@ Notas de runtime:
|
|
|
416
416
|
- em `optionSource`, o filtro envia `includeIds` somente quando `optionSource.includeIds=true` e nao ha termo de busca ativo; quando ausente, `false` ou durante busca digitada, valores selecionados sao reidratados por `/option-sources/{sourceKey}/options/by-ids`.
|
|
417
417
|
- durante busca digitada, a lista visivel usa apenas os itens da pagina remota filtrada. Opcoes reidratadas por ID preservam o display fechado, mas nao podem substituir ou inflar o resultado da busca.
|
|
418
418
|
- em `optionSource`, dependencias declaradas por `dependsOn` e `dependencyFilterMap` sao materializadas como filtros estruturados `equals` no envelope canonico de opcoes.
|
|
419
|
+
- depois da montagem inicial, a mudanca de qualquer dependencia canonica limpa o valor selecionado e o texto exibido antes de recarregar as opcoes. A limpeza emite `valueChanges` para invalidar dependentes posteriores na mesma cadeia.
|
|
420
|
+
- `optionSource.selectionPolicy.allowRetainInvalidExistingValue=true` permite reter explicitamente um valor historico; `resetOnDependentChange=false` permanece como opt-out de compatibilidade para metadata legado.
|
|
419
421
|
- `onSearch` limpa estado local e reinicia pagina para novo termo.
|
|
420
422
|
- `loadMore` nao inicia a primeira carga remota; a primeira pagina respeita `loadOn`, abertura do painel, reload explicito ou mudanca de dependencia.
|
|
421
423
|
- `loadMore` incrementa pagina somente quando ja existe pagina remota carregada e `endReached=false`.
|
|
@@ -1283,6 +1283,8 @@ declare abstract class SimpleBaseSelectComponent<T = any> extends SimpleBaseInpu
|
|
|
1283
1283
|
private ensureCurrentValueLoaded;
|
|
1284
1284
|
/** (Re)configure dependency observers based on metadata and current FormGroup */
|
|
1285
1285
|
protected setupDependencies(): void;
|
|
1286
|
+
private shouldResetOnDependencyChange;
|
|
1287
|
+
private hasMeaningfulSelectValue;
|
|
1286
1288
|
protected extractDependencyValue(raw: any, path?: string): any;
|
|
1287
1289
|
protected applyDependencyCriteria(fragment: Record<string, any>, strategy?: 'merge' | 'replace'): void;
|
|
1288
1290
|
protected onDependenciesChanged(): void;
|
|
@@ -2353,6 +2355,7 @@ declare class MaterialCpfCnpjInputComponent extends SimpleBaseInputComponent {
|
|
|
2353
2355
|
private shouldApplySemanticDocumentValidator;
|
|
2354
2356
|
isReadonlyEffective(): boolean;
|
|
2355
2357
|
writeValue(value: unknown): void;
|
|
2358
|
+
protected applyNativeDisplayMask(value?: unknown): void;
|
|
2356
2359
|
handleInput(event: Event): void;
|
|
2357
2360
|
private cleanValue;
|
|
2358
2361
|
private formatValue;
|