diff --git a/npm/ng-packs/apps/dev-app/src/app/home/custom-input.ts b/npm/ng-packs/apps/dev-app/src/app/home/custom-input.ts
deleted file mode 100644
index 9d1aeeab26..0000000000
--- a/npm/ng-packs/apps/dev-app/src/app/home/custom-input.ts
+++ /dev/null
@@ -1,124 +0,0 @@
-import {
- ChangeDetectionStrategy,
- ChangeDetectorRef,
- Component,
- DestroyRef,
- forwardRef,
- inject,
- Injector,
- input,
- OnInit,
-} from '@angular/core';
-import {
- ControlValueAccessor,
- FormBuilder,
- FormControl,
- FormControlName,
- FormGroupDirective,
- NG_VALUE_ACCESSOR,
- NgControl,
- FormGroup,
- ReactiveFormsModule,
-} from '@angular/forms';
-import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
-import { FormFieldConfig } from '@abp/ng.components/dynamic-form';
-
-
-const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR = {
- provide: NG_VALUE_ACCESSOR,
- useExisting: forwardRef(() => AppCustomInputComponent),
- multi: true,
-};
-
-@Component({
- selector: 'abp-dynamic-form-field',
- template: `
-
-
-
- `,
- providers: [
- CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR
- ],
- changeDetection: ChangeDetectionStrategy.OnPush,
- imports: [ReactiveFormsModule],
-})
-export class AppCustomInputComponent implements OnInit, ControlValueAccessor {
- field = input.required();
- visible = input(true);
- control!: FormControl;
- fieldFormGroup: FormGroup;
- readonly changeDetectorRef = inject(ChangeDetectorRef);
- readonly destroyRef = inject(DestroyRef);
- private injector = inject(Injector);
- private formBuilder = inject(FormBuilder);
-
- constructor() {
- this.fieldFormGroup = this.formBuilder.group({
- value: [{ value: '' }]
- });
- }
-
- ngOnInit() {
- const ngControl = this.injector.get(NgControl, null);
- if (ngControl) {
- this.control = this.injector.get(FormGroupDirective).getControl(ngControl as FormControlName);
- }
- this.value.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(value => {
- this.onChange(value);
- });
- }
-
- writeValue(value: any[]): void {
- this.value.setValue(value || '');
- this.changeDetectorRef.markForCheck();
- }
-
- registerOnChange(fn: any): void {
- this.onChange = fn;
- }
-
- registerOnTouched(fn: any): void {
- this.onTouched = fn;
- }
-
- setDisabledState(isDisabled: boolean): void {
- if (isDisabled) {
- this.value.disable();
- } else {
- this.value.enable();
- }
- this.changeDetectorRef.markForCheck();
- }
-
- get isInvalid(): boolean {
- if (this.control) {
- return (this.control.invalid && (this.control.dirty || this.control.touched));
- }
- return false;
- }
-
- get errors(): string[] {
- 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());
- console.log(this.field().validators, key);
- if (validator && validator.message) {
- return validator.message;
- }
- // 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}`;
- return `${this.field().label} is invalid due to ${key} validation.`;
- });
- }
- }
- get value() {
- return this.fieldFormGroup.get('value');
- }
- private onChange: (value: any) => void = () => {};
- private onTouched: () => void = () => {};
-}
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 2cb48ec299..5302d5cdb9 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
@@ -61,16 +61,16 @@ export class DynamicFormFieldComponent implements OnInit, ControlValueAccessor {
private dynamicFormService = inject(DynamicFormService);
options$: Observable<{ key: string; value: any }[]> = of([]);
-
+
// Accessibility: Generate unique IDs for ARIA
get fieldId(): string {
return `field-${this.field().key}`;
}
-
+
get errorId(): string {
return `${this.fieldId}-error`;
}
-
+
get helpTextId(): string {
return `${this.fieldId}-help`;
}
@@ -138,6 +138,7 @@ export class DynamicFormFieldComponent implements OnInit, ControlValueAccessor {
}
get errors(): string[] {
+ if (!this.control?.errors) return [];
if (this.control && this.control.errors) {
const errorKeys = Object.keys(this.control.errors);
const validators = this.field().validators || [];