@vipsolucoes/dynamic-form 1.0.7 → 1.0.9
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/README.md
CHANGED
|
@@ -137,6 +137,8 @@ A biblioteca suporta os seguintes tipos de campos:
|
|
|
137
137
|
|
|
138
138
|
### Campo Select
|
|
139
139
|
|
|
140
|
+
#### Formato Padrão (Dados Fixos)
|
|
141
|
+
|
|
140
142
|
```typescript
|
|
141
143
|
{
|
|
142
144
|
key: 'pais',
|
|
@@ -152,6 +154,135 @@ A biblioteca suporta os seguintes tipos de campos:
|
|
|
152
154
|
}
|
|
153
155
|
```
|
|
154
156
|
|
|
157
|
+
#### Com Dados de API (Sem Mapeamento Manual)
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
// Service retorna dados brutos: [{ id: 1, nome: 'São Paulo', uf: 'SP' }, ...]
|
|
161
|
+
|
|
162
|
+
{
|
|
163
|
+
key: 'cidade',
|
|
164
|
+
controlType: 'select',
|
|
165
|
+
label: 'Cidade',
|
|
166
|
+
options: [],
|
|
167
|
+
optionLabel: 'nome', // Campo do objeto para label
|
|
168
|
+
optionValue: 'id', // Campo do objeto para value
|
|
169
|
+
optionFilter: true, // Habilita filtro de busca
|
|
170
|
+
optionShowClear: true, // Mostra botão limpar
|
|
171
|
+
validators: [Validators.required]
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// No componente, passe os dados diretamente:
|
|
175
|
+
this.service.loadCidades().subscribe(cidades => {
|
|
176
|
+
this.atualizarCampo('cidade', { options: cidades });
|
|
177
|
+
});
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
#### Com optionMapper (Labels Compostos)
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
{
|
|
184
|
+
key: 'cidade',
|
|
185
|
+
controlType: 'select',
|
|
186
|
+
label: 'Cidade',
|
|
187
|
+
options: [],
|
|
188
|
+
optionMapper: (cidade) => ({
|
|
189
|
+
label: `${cidade.nome} - ${cidade.uf}`, // Label composto
|
|
190
|
+
value: cidade.id
|
|
191
|
+
}),
|
|
192
|
+
optionFilter: true,
|
|
193
|
+
validators: [Validators.required]
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
**Propriedades Disponíveis:**
|
|
198
|
+
|
|
199
|
+
- `optionLabel?`: Nome do campo para label (default: `'label'`)
|
|
200
|
+
- `optionValue?`: Nome do campo para value (default: `'value'`)
|
|
201
|
+
- `optionMapper?`: Função para mapear itens (tem prioridade sobre optionLabel/optionValue)
|
|
202
|
+
- `optionFilter?`: Habilita filtro de busca
|
|
203
|
+
- `optionShowClear?`: Mostra botão para limpar seleção
|
|
204
|
+
|
|
205
|
+
### Campo Number
|
|
206
|
+
|
|
207
|
+
O campo `number` suporta números inteiros, decimais e monetários com muitas opções de formatação:
|
|
208
|
+
|
|
209
|
+
#### Números Inteiros (Padrão)
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
{
|
|
213
|
+
key: 'quantidade',
|
|
214
|
+
controlType: 'number',
|
|
215
|
+
label: 'Quantidade',
|
|
216
|
+
validators: [Validators.required, Validators.min(1)]
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
#### Campo Monetário (Currency)
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
{
|
|
224
|
+
key: 'preco',
|
|
225
|
+
controlType: 'number',
|
|
226
|
+
label: 'Preço',
|
|
227
|
+
numberConfig: {
|
|
228
|
+
mode: 'currency',
|
|
229
|
+
currency: 'BRL',
|
|
230
|
+
locale: 'pt-BR',
|
|
231
|
+
minFractionDigits: 2,
|
|
232
|
+
maxFractionDigits: 2
|
|
233
|
+
},
|
|
234
|
+
validators: [Validators.required, Validators.min(0)]
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
#### Campo com Prefixo/Sufixo
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
{
|
|
242
|
+
key: 'desconto',
|
|
243
|
+
controlType: 'number',
|
|
244
|
+
label: 'Desconto',
|
|
245
|
+
numberConfig: {
|
|
246
|
+
prefix: '%',
|
|
247
|
+
min: 0,
|
|
248
|
+
max: 100,
|
|
249
|
+
showButtons: true
|
|
250
|
+
},
|
|
251
|
+
validators: [Validators.required, Validators.min(0), Validators.max(100)]
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
#### Campo Decimal com Unidade
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
{
|
|
259
|
+
key: 'peso',
|
|
260
|
+
controlType: 'number',
|
|
261
|
+
label: 'Peso',
|
|
262
|
+
numberConfig: {
|
|
263
|
+
mode: 'decimal',
|
|
264
|
+
suffix: ' kg',
|
|
265
|
+
minFractionDigits: 2,
|
|
266
|
+
maxFractionDigits: 3,
|
|
267
|
+
showClear: true
|
|
268
|
+
},
|
|
269
|
+
validators: [Validators.required, Validators.min(0)]
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
**Propriedades Disponíveis em `numberConfig`:**
|
|
274
|
+
|
|
275
|
+
- `mode`: `'decimal'` | `'currency'`
|
|
276
|
+
- `currency`: Código da moeda (ISO 4217) - obrigatório para currency
|
|
277
|
+
- `prefix`: Texto antes do valor (ex: `'R$'`, `'%'`)
|
|
278
|
+
- `suffix`: Texto após o valor (ex: `' kg'`, `' m²'`)
|
|
279
|
+
- `min` / `max`: Valores mínimo e máximo
|
|
280
|
+
- `minFractionDigits` / `maxFractionDigits`: Casas decimais
|
|
281
|
+
- `showButtons`: Exibir botões de incremento/decremento
|
|
282
|
+
- `showClear`: Exibir botão para limpar valor
|
|
283
|
+
- `locale`: Localização para formatação (ex: `'pt-BR'`, `'en-US'`)
|
|
284
|
+
- E muitas outras opções...
|
|
285
|
+
|
|
155
286
|
### Campo DatePicker
|
|
156
287
|
|
|
157
288
|
```typescript
|
|
@@ -337,7 +468,12 @@ interface iFormConfig {
|
|
|
337
468
|
disabled?: boolean; // Campo desabilitado
|
|
338
469
|
enabledWhen?: string; // Chave do toggle que controla este campo
|
|
339
470
|
styleClass?: string; // Classes CSS customizadas
|
|
340
|
-
options?: iFieldOption[]; // Opções para select (obrigatório se controlType for 'select')
|
|
471
|
+
options?: iFieldOption[] | unknown[]; // Opções para select (obrigatório se controlType for 'select')
|
|
472
|
+
optionLabel?: string; // Campo do objeto para label no select (default: 'label')
|
|
473
|
+
optionValue?: string; // Campo do objeto para value no select (default: 'value')
|
|
474
|
+
optionMapper?: (item: any) => iFieldOption; // Função para mapear itens (tem prioridade sobre optionLabel/optionValue)
|
|
475
|
+
optionFilter?: boolean; // Habilita filtro de busca no select
|
|
476
|
+
optionShowClear?: boolean; // Mostra botão para limpar seleção no select
|
|
341
477
|
validators?: ValidatorFn[]; // Validadores Angular
|
|
342
478
|
dateFormat?: string; // Formato da data (default: 'dd/mm/yy')
|
|
343
479
|
dateViewType?: 'date' | 'month' | 'year'; // Tipo de visualização da data (default: 'date')
|
|
@@ -346,14 +482,44 @@ interface iFormConfig {
|
|
|
346
482
|
textareaCols?: number; // Número de colunas do textarea
|
|
347
483
|
toggleTrueValue?: any; // Valor quando toggle está ativo (default: true)
|
|
348
484
|
toggleFalseValue?: any; // Valor quando toggle está inativo (default: false)
|
|
349
|
-
buttonConfig?: {
|
|
485
|
+
buttonConfig?: {
|
|
486
|
+
// Configuração do botão para campos 'input-button'
|
|
350
487
|
icon?: string; // Ícone do PrimeIcons
|
|
351
488
|
label?: string; // Texto do botão
|
|
352
489
|
tooltip?: string; // Tooltip do botão
|
|
353
490
|
position?: 'left' | 'right'; // Posição do botão (default: 'right')
|
|
354
|
-
severity?:
|
|
491
|
+
severity?:
|
|
492
|
+
| 'primary'
|
|
493
|
+
| 'secondary'
|
|
494
|
+
| 'success'
|
|
495
|
+
| 'info'
|
|
496
|
+
| 'warning'
|
|
497
|
+
| 'danger'
|
|
498
|
+
| 'help'
|
|
499
|
+
| 'contrast'; // Estilo do botão
|
|
355
500
|
};
|
|
356
501
|
buttonCallback?: (fieldKey: string, fieldValue: any) => void | Promise<void>; // Callback executado ao clicar no botão
|
|
502
|
+
numberConfig?: {
|
|
503
|
+
// Configuração específica para campos 'number'
|
|
504
|
+
mode?: 'decimal' | 'currency';
|
|
505
|
+
currency?: string; // Código da moeda (ISO 4217)
|
|
506
|
+
currencyDisplay?: 'symbol' | 'code' | 'name';
|
|
507
|
+
minFractionDigits?: number;
|
|
508
|
+
maxFractionDigits?: number;
|
|
509
|
+
useGrouping?: boolean;
|
|
510
|
+
prefix?: string;
|
|
511
|
+
suffix?: string;
|
|
512
|
+
min?: number;
|
|
513
|
+
max?: number;
|
|
514
|
+
step?: number;
|
|
515
|
+
showButtons?: boolean;
|
|
516
|
+
buttonLayout?: 'stacked' | 'horizontal' | 'vertical';
|
|
517
|
+
showClear?: boolean;
|
|
518
|
+
locale?: string;
|
|
519
|
+
readonly?: boolean;
|
|
520
|
+
size?: 'small' | 'large';
|
|
521
|
+
variant?: 'outlined' | 'filled';
|
|
522
|
+
};
|
|
357
523
|
}
|
|
358
524
|
```
|
|
359
525
|
|
|
@@ -47,6 +47,8 @@ class DynamicFormErrorComponent {
|
|
|
47
47
|
email: () => this.customMessages?.email ?? 'Por favor, insira um e-mail válido.',
|
|
48
48
|
minlength: (err) => this.customMessages?.minlength?.(err.requiredLength) ?? `Mínimo de ${err.requiredLength} caracteres.`,
|
|
49
49
|
maxlength: (err) => this.customMessages?.maxlength?.(err.requiredLength) ?? `Máximo de ${err.requiredLength} caracteres.`,
|
|
50
|
+
min: (err) => this.customMessages?.min?.(err.min) ?? `O valor mínimo é ${err.min}.`,
|
|
51
|
+
max: (err) => this.customMessages?.max?.(err.max) ?? `O valor máximo é ${err.max}.`,
|
|
50
52
|
custom: (err) => (this.customMessages?.custom ? this.customMessages.custom(err) : err),
|
|
51
53
|
};
|
|
52
54
|
// Getter simples - Angular detecta mudanças automaticamente
|
|
@@ -459,22 +461,163 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.7", ngImpor
|
|
|
459
461
|
class NumberInputFieldComponent {
|
|
460
462
|
form = input.required(...(ngDevMode ? [{ debugName: "form" }] : []));
|
|
461
463
|
field = input.required(...(ngDevMode ? [{ debugName: "field" }] : []));
|
|
464
|
+
/**
|
|
465
|
+
* Retorna a configuração numberConfig do campo, se existir.
|
|
466
|
+
*/
|
|
467
|
+
numberConfig = computed(() => this.field().numberConfig, ...(ngDevMode ? [{ debugName: "numberConfig" }] : []));
|
|
468
|
+
/**
|
|
469
|
+
* Determina o modo efetivo do InputNumber.
|
|
470
|
+
* Se não houver numberConfig, retorna undefined (comportamento padrão para inteiros).
|
|
471
|
+
* Se houver numberConfig mas mode não estiver definido, retorna 'decimal'.
|
|
472
|
+
*/
|
|
473
|
+
effectiveMode = computed(() => {
|
|
474
|
+
const config = this.numberConfig();
|
|
475
|
+
if (!config) {
|
|
476
|
+
return undefined; // Comportamento padrão (inteiros)
|
|
477
|
+
}
|
|
478
|
+
return config.mode ?? 'decimal';
|
|
479
|
+
}, ...(ngDevMode ? [{ debugName: "effectiveMode" }] : []));
|
|
480
|
+
/**
|
|
481
|
+
* Determina a localização efetiva.
|
|
482
|
+
* Se não especificada no numberConfig, retorna undefined (usa localização do navegador).
|
|
483
|
+
*/
|
|
484
|
+
effectiveLocale = computed(() => {
|
|
485
|
+
return this.numberConfig()?.locale;
|
|
486
|
+
}, ...(ngDevMode ? [{ debugName: "effectiveLocale" }] : []));
|
|
487
|
+
/**
|
|
488
|
+
* Determina o número mínimo de casas decimais.
|
|
489
|
+
* Para currency mode, default é 2. Para decimal mode, default é 0.
|
|
490
|
+
* Se não houver numberConfig, retorna undefined (comportamento padrão para inteiros).
|
|
491
|
+
*/
|
|
492
|
+
effectiveMinFractionDigits = computed(() => {
|
|
493
|
+
const config = this.numberConfig();
|
|
494
|
+
if (!config) {
|
|
495
|
+
return undefined; // Comportamento padrão (inteiros)
|
|
496
|
+
}
|
|
497
|
+
if (config.minFractionDigits !== undefined) {
|
|
498
|
+
return config.minFractionDigits;
|
|
499
|
+
}
|
|
500
|
+
// Default baseado no mode
|
|
501
|
+
return config.mode === 'currency' ? 2 : 0;
|
|
502
|
+
}, ...(ngDevMode ? [{ debugName: "effectiveMinFractionDigits" }] : []));
|
|
503
|
+
/**
|
|
504
|
+
* Determina o número máximo de casas decimais.
|
|
505
|
+
* Para currency mode, default é 2. Para decimal mode, default é 3.
|
|
506
|
+
* Se não houver numberConfig, retorna undefined (comportamento padrão para inteiros).
|
|
507
|
+
*/
|
|
508
|
+
effectiveMaxFractionDigits = computed(() => {
|
|
509
|
+
const config = this.numberConfig();
|
|
510
|
+
if (!config) {
|
|
511
|
+
return undefined; // Comportamento padrão (inteiros)
|
|
512
|
+
}
|
|
513
|
+
if (config.maxFractionDigits !== undefined) {
|
|
514
|
+
return config.maxFractionDigits;
|
|
515
|
+
}
|
|
516
|
+
// Default baseado no mode
|
|
517
|
+
return config.mode === 'currency' ? 2 : 3;
|
|
518
|
+
}, ...(ngDevMode ? [{ debugName: "effectiveMaxFractionDigits" }] : []));
|
|
519
|
+
/**
|
|
520
|
+
* Verifica se deve exibir botões de incremento/decremento.
|
|
521
|
+
*/
|
|
522
|
+
hasButtons = computed(() => {
|
|
523
|
+
return this.numberConfig()?.showButtons ?? false;
|
|
524
|
+
}, ...(ngDevMode ? [{ debugName: "hasButtons" }] : []));
|
|
525
|
+
/**
|
|
526
|
+
* Verifica se deve exibir botão para limpar valor.
|
|
527
|
+
*/
|
|
528
|
+
hasClearButton = computed(() => {
|
|
529
|
+
return this.numberConfig()?.showClear ?? false;
|
|
530
|
+
}, ...(ngDevMode ? [{ debugName: "hasClearButton" }] : []));
|
|
531
|
+
/**
|
|
532
|
+
* Verifica se o campo está em estado inválido.
|
|
533
|
+
*/
|
|
534
|
+
isInvalid = computed(() => {
|
|
535
|
+
const control = this.form().get(this.field().key);
|
|
536
|
+
if (!control) {
|
|
537
|
+
return false;
|
|
538
|
+
}
|
|
539
|
+
return control.invalid && (control.touched || control.dirty);
|
|
540
|
+
}, ...(ngDevMode ? [{ debugName: "isInvalid" }] : []));
|
|
541
|
+
/**
|
|
542
|
+
* Verifica se o campo tem validação required.
|
|
543
|
+
*/
|
|
544
|
+
hasRequiredValidator = computed(() => {
|
|
545
|
+
const control = this.form().get(this.field().key);
|
|
546
|
+
if (!control) {
|
|
547
|
+
return false;
|
|
548
|
+
}
|
|
549
|
+
return control.hasError('required');
|
|
550
|
+
}, ...(ngDevMode ? [{ debugName: "hasRequiredValidator" }] : []));
|
|
462
551
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.7", ngImport: i0, type: NumberInputFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
463
552
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.7", type: NumberInputFieldComponent, isStandalone: true, selector: "vp-number-input-field", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null }, field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: `
|
|
464
553
|
<div [formGroup]="form()">
|
|
465
554
|
<p-iftalabel>
|
|
466
|
-
<p-inputNumber
|
|
555
|
+
<p-inputNumber
|
|
556
|
+
[inputId]="field().key"
|
|
557
|
+
[formControlName]="field().key"
|
|
558
|
+
[placeholder]="field().placeholder || ''"
|
|
559
|
+
[mode]="effectiveMode() ?? undefined"
|
|
560
|
+
[currency]="numberConfig()?.currency ?? undefined"
|
|
561
|
+
[currencyDisplay]="numberConfig()?.currencyDisplay ?? undefined"
|
|
562
|
+
[minFractionDigits]="effectiveMinFractionDigits() ?? undefined"
|
|
563
|
+
[maxFractionDigits]="effectiveMaxFractionDigits() ?? undefined"
|
|
564
|
+
[useGrouping]="numberConfig()?.useGrouping ?? true"
|
|
565
|
+
[prefix]="numberConfig()?.prefix ?? undefined"
|
|
566
|
+
[suffix]="numberConfig()?.suffix ?? undefined"
|
|
567
|
+
[min]="numberConfig()?.min ?? undefined"
|
|
568
|
+
[max]="numberConfig()?.max ?? undefined"
|
|
569
|
+
[step]="numberConfig()?.step ?? undefined"
|
|
570
|
+
[showButtons]="hasButtons()"
|
|
571
|
+
[buttonLayout]="numberConfig()?.buttonLayout ?? 'stacked'"
|
|
572
|
+
[showClear]="hasClearButton()"
|
|
573
|
+
[locale]="effectiveLocale() ?? undefined"
|
|
574
|
+
[readonly]="numberConfig()?.readonly ?? false"
|
|
575
|
+
[size]="numberConfig()?.size ?? undefined"
|
|
576
|
+
[variant]="numberConfig()?.variant ?? 'outlined'"
|
|
577
|
+
[invalid]="isInvalid()"
|
|
578
|
+
[disabled]="field().disabled ?? false"
|
|
579
|
+
[required]="hasRequiredValidator()"
|
|
580
|
+
styleClass="w-full"
|
|
581
|
+
class="w-full"
|
|
582
|
+
/>
|
|
467
583
|
<label [for]="field().key">{{ field().label }}</label>
|
|
468
584
|
</p-iftalabel>
|
|
469
585
|
</div>
|
|
470
|
-
`, isInline: true, styles: [":host{display:block;width:100%}p-iftalabel{display:block;width:100%}:host ::ng-deep p-inputNumber,:host ::ng-deep .p-inputnumber,:host ::ng-deep .p-inputnumber input{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: IftaLabelModule }, { kind: "component", type: i2.IftaLabel, selector: "p-iftalabel, p-iftaLabel, p-ifta-label" }, { kind: "ngmodule", type: InputNumberModule }, { kind: "component", type: i3$2.InputNumber, selector: "p-inputNumber, p-inputnumber, p-input-number", inputs: ["showButtons", "format", "buttonLayout", "inputId", "styleClass", "placeholder", "tabindex", "title", "ariaLabelledBy", "ariaDescribedBy", "ariaLabel", "ariaRequired", "autocomplete", "incrementButtonClass", "decrementButtonClass", "incrementButtonIcon", "decrementButtonIcon", "readonly", "allowEmpty", "locale", "localeMatcher", "mode", "currency", "currencyDisplay", "useGrouping", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "inputStyle", "inputStyleClass", "showClear", "autofocus"], outputs: ["onInput", "onFocus", "onBlur", "onKeyDown", "onClear"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
586
|
+
`, isInline: true, styles: [":host{display:block;width:100%}p-iftalabel{display:block;width:100%}:host ::ng-deep p-inputNumber,:host ::ng-deep .p-inputnumber,:host ::ng-deep .p-inputnumber input{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: IftaLabelModule }, { kind: "component", type: i2.IftaLabel, selector: "p-iftalabel, p-iftaLabel, p-ifta-label" }, { kind: "ngmodule", type: InputNumberModule }, { kind: "component", type: i3$2.InputNumber, selector: "p-inputNumber, p-inputnumber, p-input-number", inputs: ["showButtons", "format", "buttonLayout", "inputId", "styleClass", "placeholder", "tabindex", "title", "ariaLabelledBy", "ariaDescribedBy", "ariaLabel", "ariaRequired", "autocomplete", "incrementButtonClass", "decrementButtonClass", "incrementButtonIcon", "decrementButtonIcon", "readonly", "allowEmpty", "locale", "localeMatcher", "mode", "currency", "currencyDisplay", "useGrouping", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "inputStyle", "inputStyleClass", "showClear", "autofocus"], outputs: ["onInput", "onFocus", "onBlur", "onKeyDown", "onClear"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
471
587
|
}
|
|
472
588
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.7", ngImport: i0, type: NumberInputFieldComponent, decorators: [{
|
|
473
589
|
type: Component,
|
|
474
590
|
args: [{ selector: 'vp-number-input-field', standalone: true, imports: [ReactiveFormsModule, IftaLabelModule, InputNumberModule], changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
475
591
|
<div [formGroup]="form()">
|
|
476
592
|
<p-iftalabel>
|
|
477
|
-
<p-inputNumber
|
|
593
|
+
<p-inputNumber
|
|
594
|
+
[inputId]="field().key"
|
|
595
|
+
[formControlName]="field().key"
|
|
596
|
+
[placeholder]="field().placeholder || ''"
|
|
597
|
+
[mode]="effectiveMode() ?? undefined"
|
|
598
|
+
[currency]="numberConfig()?.currency ?? undefined"
|
|
599
|
+
[currencyDisplay]="numberConfig()?.currencyDisplay ?? undefined"
|
|
600
|
+
[minFractionDigits]="effectiveMinFractionDigits() ?? undefined"
|
|
601
|
+
[maxFractionDigits]="effectiveMaxFractionDigits() ?? undefined"
|
|
602
|
+
[useGrouping]="numberConfig()?.useGrouping ?? true"
|
|
603
|
+
[prefix]="numberConfig()?.prefix ?? undefined"
|
|
604
|
+
[suffix]="numberConfig()?.suffix ?? undefined"
|
|
605
|
+
[min]="numberConfig()?.min ?? undefined"
|
|
606
|
+
[max]="numberConfig()?.max ?? undefined"
|
|
607
|
+
[step]="numberConfig()?.step ?? undefined"
|
|
608
|
+
[showButtons]="hasButtons()"
|
|
609
|
+
[buttonLayout]="numberConfig()?.buttonLayout ?? 'stacked'"
|
|
610
|
+
[showClear]="hasClearButton()"
|
|
611
|
+
[locale]="effectiveLocale() ?? undefined"
|
|
612
|
+
[readonly]="numberConfig()?.readonly ?? false"
|
|
613
|
+
[size]="numberConfig()?.size ?? undefined"
|
|
614
|
+
[variant]="numberConfig()?.variant ?? 'outlined'"
|
|
615
|
+
[invalid]="isInvalid()"
|
|
616
|
+
[disabled]="field().disabled ?? false"
|
|
617
|
+
[required]="hasRequiredValidator()"
|
|
618
|
+
styleClass="w-full"
|
|
619
|
+
class="w-full"
|
|
620
|
+
/>
|
|
478
621
|
<label [for]="field().key">{{ field().label }}</label>
|
|
479
622
|
</p-iftalabel>
|
|
480
623
|
</div>
|
|
@@ -523,6 +666,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.7", ngImpor
|
|
|
523
666
|
class RadioButtonFieldComponent {
|
|
524
667
|
form = input.required(...(ngDevMode ? [{ debugName: "form" }] : []));
|
|
525
668
|
field = input.required(...(ngDevMode ? [{ debugName: "field" }] : []));
|
|
669
|
+
options = computed(() => {
|
|
670
|
+
return this.field().options;
|
|
671
|
+
}, ...(ngDevMode ? [{ debugName: "options" }] : []));
|
|
526
672
|
layout = computed(() => {
|
|
527
673
|
return this.field().radioLayout ?? 'vertical';
|
|
528
674
|
}, ...(ngDevMode ? [{ debugName: "layout" }] : []));
|
|
@@ -544,7 +690,7 @@ class RadioButtonFieldComponent {
|
|
|
544
690
|
[class.radiobutton-options-horizontal]="layout() === 'horizontal'"
|
|
545
691
|
[class.radiobutton-options-vertical]="layout() === 'vertical'"
|
|
546
692
|
>
|
|
547
|
-
@for (option of
|
|
693
|
+
@for (option of options(); track option.value) {
|
|
548
694
|
<div class="radiobutton-option">
|
|
549
695
|
<p-radiobutton
|
|
550
696
|
[formControlName]="field().key"
|
|
@@ -577,7 +723,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.7", ngImpor
|
|
|
577
723
|
[class.radiobutton-options-horizontal]="layout() === 'horizontal'"
|
|
578
724
|
[class.radiobutton-options-vertical]="layout() === 'vertical'"
|
|
579
725
|
>
|
|
580
|
-
@for (option of
|
|
726
|
+
@for (option of options(); track option.value) {
|
|
581
727
|
<div class="radiobutton-option">
|
|
582
728
|
<p-radiobutton
|
|
583
729
|
[formControlName]="field().key"
|
|
@@ -602,6 +748,40 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.7", ngImpor
|
|
|
602
748
|
class SelectFieldComponent {
|
|
603
749
|
form = input.required(...(ngDevMode ? [{ debugName: "form" }] : []));
|
|
604
750
|
field = input.required(...(ngDevMode ? [{ debugName: "field" }] : []));
|
|
751
|
+
/**
|
|
752
|
+
* Aplica optionMapper se existir, caso contrário retorna as opções originais.
|
|
753
|
+
* Prioridade: optionMapper > optionLabel/optionValue > label/value padrão
|
|
754
|
+
*/
|
|
755
|
+
mappedOptions = computed(() => {
|
|
756
|
+
const options = this.field().options ?? [];
|
|
757
|
+
const mapper = this.field().optionMapper;
|
|
758
|
+
if (mapper) {
|
|
759
|
+
return options.map(mapper);
|
|
760
|
+
}
|
|
761
|
+
return options;
|
|
762
|
+
}, ...(ngDevMode ? [{ debugName: "mappedOptions" }] : []));
|
|
763
|
+
/**
|
|
764
|
+
* Determina o optionLabel efetivo a ser usado.
|
|
765
|
+
* Se optionMapper estiver definido, usa 'label' (pois mapper já transformou).
|
|
766
|
+
* Caso contrário, usa optionLabel configurado ou 'label' como padrão.
|
|
767
|
+
*/
|
|
768
|
+
effectiveOptionLabel = computed(() => {
|
|
769
|
+
if (this.field().optionMapper) {
|
|
770
|
+
return 'label';
|
|
771
|
+
}
|
|
772
|
+
return this.field().optionLabel ?? 'label';
|
|
773
|
+
}, ...(ngDevMode ? [{ debugName: "effectiveOptionLabel" }] : []));
|
|
774
|
+
/**
|
|
775
|
+
* Determina o optionValue efetivo a ser usado.
|
|
776
|
+
* Se optionMapper estiver definido, usa 'value' (pois mapper já transformou).
|
|
777
|
+
* Caso contrário, usa optionValue configurado ou 'value' como padrão.
|
|
778
|
+
*/
|
|
779
|
+
effectiveOptionValue = computed(() => {
|
|
780
|
+
if (this.field().optionMapper) {
|
|
781
|
+
return 'value';
|
|
782
|
+
}
|
|
783
|
+
return this.field().optionValue ?? 'value';
|
|
784
|
+
}, ...(ngDevMode ? [{ debugName: "effectiveOptionValue" }] : []));
|
|
605
785
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.7", ngImport: i0, type: SelectFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
606
786
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.7", type: SelectFieldComponent, isStandalone: true, selector: "vp-select-field", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null }, field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: `
|
|
607
787
|
<div [formGroup]="form()">
|
|
@@ -609,11 +789,14 @@ class SelectFieldComponent {
|
|
|
609
789
|
<p-select
|
|
610
790
|
[inputId]="field().key"
|
|
611
791
|
[formControlName]="field().key"
|
|
612
|
-
[options]="
|
|
792
|
+
[options]="mappedOptions()"
|
|
613
793
|
[placeholder]="field().placeholder || 'Selecione'"
|
|
614
|
-
optionLabel="
|
|
615
|
-
optionValue="
|
|
616
|
-
|
|
794
|
+
[optionLabel]="effectiveOptionLabel()"
|
|
795
|
+
[optionValue]="effectiveOptionValue()"
|
|
796
|
+
[filter]="field().optionFilter ?? false"
|
|
797
|
+
[showClear]="field().optionShowClear ?? false"
|
|
798
|
+
class="w-full"
|
|
799
|
+
/>
|
|
617
800
|
<label [for]="field().key">{{ field().label }}</label>
|
|
618
801
|
</p-iftalabel>
|
|
619
802
|
</div>
|
|
@@ -627,11 +810,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.7", ngImpor
|
|
|
627
810
|
<p-select
|
|
628
811
|
[inputId]="field().key"
|
|
629
812
|
[formControlName]="field().key"
|
|
630
|
-
[options]="
|
|
813
|
+
[options]="mappedOptions()"
|
|
631
814
|
[placeholder]="field().placeholder || 'Selecione'"
|
|
632
|
-
optionLabel="
|
|
633
|
-
optionValue="
|
|
634
|
-
|
|
815
|
+
[optionLabel]="effectiveOptionLabel()"
|
|
816
|
+
[optionValue]="effectiveOptionValue()"
|
|
817
|
+
[filter]="field().optionFilter ?? false"
|
|
818
|
+
[showClear]="field().optionShowClear ?? false"
|
|
819
|
+
class="w-full"
|
|
820
|
+
/>
|
|
635
821
|
<label [for]="field().key">{{ field().label }}</label>
|
|
636
822
|
</p-iftalabel>
|
|
637
823
|
</div>
|