diff --git a/npm/ng-packs/packages/components/dynamic-form/src/dynamic-form-field/dynamic-form-field-host.component.ts b/npm/ng-packs/packages/components/dynamic-form/src/dynamic-form-field/dynamic-form-field-host.component.ts index 5ea3de44c4..54600b4e7a 100644 --- a/npm/ng-packs/packages/components/dynamic-form/src/dynamic-form-field/dynamic-form-field-host.component.ts +++ b/npm/ng-packs/packages/components/dynamic-form/src/dynamic-form-field/dynamic-form-field-host.component.ts @@ -2,8 +2,6 @@ import { Component, ViewChild, ViewContainerRef, - OnChanges, - SimpleChanges, ChangeDetectionStrategy, forwardRef, Type, @@ -34,26 +32,28 @@ type acceptsFormControl = { formControl?: FormControl }; multi: true }] }) -export class DynamicFieldHostComponent implements ControlValueAccessor, OnChanges { - component = input>(); +export class DynamicFieldHostComponent implements ControlValueAccessor { + component = input>(); inputs = input>({}); @ViewChild('vcRef', { read: ViewContainerRef, static: true }) viewContainerRef!: ViewContainerRef; private componentRef?: any; - private lastValue: any; + private value: any; private disabled = false; // if child has not implemented ControlValueAccessor. Create form control private innerControl = new FormControl(null); readonly destroyRef = inject(DestroyRef); - ngOnChanges(changes: SimpleChanges): void { - if (changes['component']) { - this.createChild(); - } else if (this.componentRef && changes['inputs']) { - this.applyInputs(); - } + constructor() { + effect(() => { + if (this.component()) { + this.createChild(); + } else if (this.componentRef && this.inputs()) { + this.applyInputs(); + } + }); } private createChild() { @@ -72,25 +72,20 @@ export class DynamicFieldHostComponent implements ControlValueAccessor, OnChange if (this.disabled && instance.setDisabledState) { instance.setDisabledState(true); } - // İlk değeri ilet - if (this.lastValue !== undefined) { - instance.writeValue?.(this.lastValue); + // set initial value + if (this.value !== undefined) { + instance.writeValue?.(this.value); } } else { - // Child CVA değilse, formControl input’u varsa köprüle + // No CVA -> use form control if ('formControl' in instance) { instance.formControl = this.innerControl; - // son değeri uygula - if (this.lastValue !== undefined) { - this.innerControl.setValue(this.lastValue, { emitEvent: false }); + // apply initial value/disabled state + if (this.value !== undefined) { + this.innerControl.setValue(this.value, { emitEvent: false }); } this.innerControl.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(v => this.onChange(v)); this.innerControl.disabled ? null : (this.disabled && this.innerControl.disable({ emitEvent: false })); - } else { - // Son çare: valueChange EventEmitter’ı varsa bağla (konvansiyonel) - if ('valueChange' in instance && instance['valueChange']?.subscribe) { - instance['valueChange'].pipe(takeUntilDestroyed(this.destroyRef)).subscribe((v: any) => this.onChange(v)); - } } } } @@ -108,10 +103,8 @@ export class DynamicFieldHostComponent implements ControlValueAccessor, OnChange return obj && typeof obj.writeValue === 'function' && typeof obj.registerOnChange === 'function'; } - /* --------- CVA (wrapper) --------- */ - writeValue(obj: any): void { - this.lastValue = obj; + this.value = obj; if (!this.componentRef) return; const inst: any = this.componentRef.instance as controlValueAccessorLike & acceptsFormControl; diff --git a/npm/ng-packs/packages/components/dynamic-form/src/dynamic-form-field/dynamic-form-field.component.html b/npm/ng-packs/packages/components/dynamic-form/src/dynamic-form-field/dynamic-form-field.component.html index b2b95a5e3c..8bd9ad1fbf 100644 --- a/npm/ng-packs/packages/components/dynamic-form/src/dynamic-form-field/dynamic-form-field.component.html +++ b/npm/ng-packs/packages/components/dynamic-form/src/dynamic-form-field/dynamic-form-field.component.html @@ -38,15 +38,7 @@ } @else if (field().type === 'checkbox') {
- - + @if (isInvalid) { } diff --git a/npm/ng-packs/packages/components/dynamic-form/src/dynamic-form-field/dynamic-form-field.component.ts b/npm/ng-packs/packages/components/dynamic-form/src/dynamic-form-field/dynamic-form-field.component.ts index fce9058680..f7bd449352 100644 --- a/npm/ng-packs/packages/components/dynamic-form/src/dynamic-form-field/dynamic-form-field.component.ts +++ b/npm/ng-packs/packages/components/dynamic-form/src/dynamic-form-field/dynamic-form-field.component.ts @@ -16,7 +16,6 @@ import { FormControl, FormControlName, FormGroupDirective, - FormsModule, NG_VALUE_ACCESSOR, NgControl, FormGroup, @@ -25,6 +24,7 @@ import { import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { NgTemplateOutlet } from '@angular/common'; import { LocalizationPipe } from '@abp/ng.core'; +import { FormCheckboxComponent } from '@abp/ng.theme.shared'; export const ABP_DYNAMIC_FORM_FIELD = new InjectionToken('AbpDynamicFormField'); @@ -40,12 +40,12 @@ const DYNAMIC_FORM_FIELD_CONTROL_VALUE_ACCESSOR = { styleUrls: ['./dynamic-form-field.component.scss'], providers: [ { provide: ABP_DYNAMIC_FORM_FIELD, useExisting: DynamicFormFieldComponent }, - DYNAMIC_FORM_FIELD_CONTROL_VALUE_ACCESSOR + DYNAMIC_FORM_FIELD_CONTROL_VALUE_ACCESSOR, ], host: { class: 'abp-dynamic-form-field' }, exportAs: 'abpDynamicFormField', changeDetection: ChangeDetectionStrategy.OnPush, - imports: [NgTemplateOutlet, LocalizationPipe, ReactiveFormsModule], + imports: [NgTemplateOutlet, LocalizationPipe, ReactiveFormsModule, FormCheckboxComponent], }) export class DynamicFormFieldComponent implements OnInit, ControlValueAccessor { field = input.required(); @@ -59,7 +59,7 @@ export class DynamicFormFieldComponent implements OnInit, ControlValueAccessor { constructor() { this.fieldFormGroup = this.formBuilder.group({ - value: [{ value: '' }] + value: [{ value: '' }], }); } @@ -97,7 +97,7 @@ export class DynamicFormFieldComponent implements OnInit, ControlValueAccessor { get isInvalid(): boolean { if (this.control) { - return (this.control.invalid && (this.control.dirty || this.control.touched)); + return this.control.invalid && (this.control.dirty || this.control.touched); } return false; } @@ -106,7 +106,9 @@ export class DynamicFormFieldComponent implements OnInit, ControlValueAccessor { if (this.control && this.control.errors) { const errorKeys = Object.keys(this.control.errors); return errorKeys.map(key => { - const validator = this.field().validators.find(v => v.type.toLowerCase() === key.toLowerCase()); + const validator = this.field().validators.find( + v => v.type.toLowerCase() === key.toLowerCase(), + ); console.log(this.field().validators, key); if (validator && validator.message) { return validator.message; @@ -114,8 +116,10 @@ export class DynamicFormFieldComponent implements OnInit, ControlValueAccessor { // Fallback error messages if (key === 'required') return `${this.field().label} is required`; if (key === 'email') return 'Please enter a valid email address'; - if (key === 'minlength') return `Minimum length is ${this.control.errors[key].requiredLength}`; - if (key === 'maxlength') return `Maximum length is ${this.control.errors[key].requiredLength}`; + if (key === 'minlength') + return `Minimum length is ${this.control.errors[key].requiredLength}`; + if (key === 'maxlength') + return `Maximum length is ${this.control.errors[key].requiredLength}`; return `${this.field().label} is invalid due to ${key} validation.`; }); } diff --git a/npm/ng-packs/packages/components/dynamic-form/src/dynamic-form.models.ts b/npm/ng-packs/packages/components/dynamic-form/src/dynamic-form.models.ts index c32163d4ac..716c252d7b 100644 --- a/npm/ng-packs/packages/components/dynamic-form/src/dynamic-form.models.ts +++ b/npm/ng-packs/packages/components/dynamic-form/src/dynamic-form.models.ts @@ -1,3 +1,5 @@ +import { Type } from '@angular/core'; +import { ControlValueAccessor } from '@angular/forms'; export interface FormFieldConfig { key: string; @@ -12,7 +14,7 @@ export interface FormFieldConfig { conditionalLogic?: ConditionalRule[]; order?: number; gridSize?: number; - component?: any; + component?: Type; } export interface ValidatorConfig {