Browse Source

dynamic options support added

pull/24547/head
erdemcaygor 8 months ago
parent
commit
77f16cbef7
  1. 2
      npm/ng-packs/packages/components/dynamic-form/src/dynamic-form-field/dynamic-form-field.component.html
  2. 30
      npm/ng-packs/packages/components/dynamic-form/src/dynamic-form-field/dynamic-form-field.component.ts
  3. 13
      npm/ng-packs/packages/components/dynamic-form/src/dynamic-form.models.ts
  4. 12
      npm/ng-packs/packages/components/dynamic-form/src/dynamic-form.service.ts

2
npm/ng-packs/packages/components/dynamic-form/src/dynamic-form-field/dynamic-form-field.component.html

@ -16,7 +16,7 @@
<ng-container [ngTemplateOutlet]="labelTemplate" />
<select [id]="field().key" formControlName="value" [class.is-invalid]="isInvalid" class="form-control">
<option value="">{{ '::Select' | abpLocalization }}</option>
@for (option of field().options; track option.key) {
@for (option of options$ | async; track option.key) {
<option [value]="option.key">
{{ option.value | abpLocalization }}
</option>

30
npm/ng-packs/packages/components/dynamic-form/src/dynamic-form-field/dynamic-form-field.component.ts

@ -22,9 +22,11 @@ import {
ReactiveFormsModule,
} from '@angular/forms';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { NgTemplateOutlet } from '@angular/common';
import { NgTemplateOutlet, AsyncPipe } from '@angular/common';
import { LocalizationPipe } from '@abp/ng.core';
import { FormCheckboxComponent } from '@abp/ng.theme.shared';
import { Observable, of } from 'rxjs';
import { DynamicFormService } from '../dynamic-form.service';
export const ABP_DYNAMIC_FORM_FIELD = new InjectionToken<DynamicFormFieldComponent>('AbpDynamicFormField');
@ -45,7 +47,7 @@ const DYNAMIC_FORM_FIELD_CONTROL_VALUE_ACCESSOR = {
host: { class: 'abp-dynamic-form-field' },
exportAs: 'abpDynamicFormField',
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [NgTemplateOutlet, LocalizationPipe, ReactiveFormsModule, FormCheckboxComponent],
imports: [NgTemplateOutlet, LocalizationPipe, ReactiveFormsModule, FormCheckboxComponent, AsyncPipe],
})
export class DynamicFormFieldComponent implements OnInit, ControlValueAccessor {
field = input.required<FormFieldConfig>();
@ -56,6 +58,9 @@ export class DynamicFormFieldComponent implements OnInit, ControlValueAccessor {
readonly destroyRef = inject(DestroyRef);
private injector = inject(Injector);
private formBuilder = inject(FormBuilder);
private dynamicFormService = inject(DynamicFormService);
options$: Observable<{ key: string; value: any }[]> = of([]);
constructor() {
this.fieldFormGroup = this.formBuilder.group({
@ -71,6 +76,23 @@ export class DynamicFormFieldComponent implements OnInit, ControlValueAccessor {
this.value.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(value => {
this.onChange(value);
});
const options = this.field().options;
if (options?.url) {
this.options$ = this.dynamicFormService.getOptions(options.url, options.apiName);
} else if (options?.defaultValues?.length) {
this.options$ = of(
options.defaultValues.map(item => {
return {
key: item[options.valueProp || 'key'] || item,
value: item[options.labelProp || 'value'] || item
};
})
);
} else {
this.options$ = of([]);
}
}
writeValue(value: any[]): void {
@ -127,6 +149,6 @@ export class DynamicFormFieldComponent implements OnInit, ControlValueAccessor {
get value() {
return this.fieldFormGroup.get('value');
}
private onChange: (value: any) => void = () => {};
private onTouched: () => void = () => {};
private onChange: (value: any) => void = () => { };
private onTouched: () => void = () => { };
}

13
npm/ng-packs/packages/components/dynamic-form/src/dynamic-form.models.ts

@ -1,7 +1,7 @@
import { Type } from '@angular/core';
import { ControlValueAccessor } from '@angular/forms';
export interface FormFieldConfig {
export interface FormFieldConfig<T = any> {
key: string;
value?: any;
type: 'text' | 'email' | 'number' | 'select' | 'checkbox' | 'date' | 'textarea';
@ -9,7 +9,7 @@ export interface FormFieldConfig {
placeholder?: string;
required?: boolean;
disabled?: boolean;
options?: { key: string; value: any }[];
options?: OptionProps<T>;
validators?: ValidatorConfig[];
conditionalLogic?: ConditionalRule[];
order?: number;
@ -36,3 +36,12 @@ export enum ConditionalAction {
ENABLE = 'enable',
DISABLE = 'disable'
}
export interface OptionProps<T = any> {
defaultValues?: T[];
url?: string;
disabled?: (option: T) => boolean;
labelProp?: string;
valueProp?: string;
apiName?: string;
}

12
npm/ng-packs/packages/components/dynamic-form/src/dynamic-form.service.ts

@ -1,6 +1,8 @@
import {Injectable, inject} from '@angular/core';
import {FormControl, FormGroup, ValidatorFn, Validators, FormBuilder} from '@angular/forms';
import {FormFieldConfig, ValidatorConfig} from './dynamic-form.models';
import { RestService } from '@abp/ng.core';
import type { ProfileDto } from '@abp/ng.account.core/proxy';
@Injectable({
providedIn: 'root'
@ -9,6 +11,8 @@ import {FormFieldConfig, ValidatorConfig} from './dynamic-form.models';
export class DynamicFormService {
private formBuilder = inject(FormBuilder);
private restService = inject(RestService);
apiName = 'DynamicFormService';
createFormGroup(fields: FormFieldConfig[]): FormGroup {
const group: any = {};
@ -34,6 +38,14 @@ export class DynamicFormService {
return initialValues;
}
getOptions(url: string, apiName?: string): any {
return this.restService.request<any, any[]>({
method: 'GET',
url,
},
{ apiName: apiName || this.apiName });
}
private buildValidators(validatorConfigs: ValidatorConfig[]): ValidatorFn[] {
return validatorConfigs.map(config => {
switch (config.type) {

Loading…
Cancel
Save