Skip to content

Conversation

@erdemcaygor
Copy link
Contributor

@erdemcaygor erdemcaygor commented Oct 8, 2025

Resolves #23891

Config Interfaces

export interface FormFieldConfig {
  key: string;
  value?: any;
  type: 'text' | 'email' | 'number' | 'select' | 'checkbox' | 'date' | 'textarea';
  label: string;
  placeholder?: string;
  required?: boolean;
  disabled?: boolean;
  options?: { key: string; value: any }[];
  validators?: ValidatorConfig[];
  conditionalLogic?: ConditionalRule[];
  order?: number;
  gridSize?: number;
  component?: Type<ControlValueAccessor>;
}

export interface ValidatorConfig {
  type: 'required' | 'email' | 'minLength' | 'maxLength' | 'pattern' | 'custom' | 'min' | 'max' | 'requiredTrue';
  value?: any;
  message: string;
}

export interface ConditionalRule {
  dependsOn: string;
  condition: 'equals' | 'notEquals' | 'contains' | 'greaterThan' | 'lessThan';
  value: any;
  action: 'show' | 'hide' | 'enable' | 'disable';
}

Example Usage

  formFields: FormFieldConfig[] = [
    {
      key: 'firstName',
      type: 'text',
      label: 'First Name',
      placeholder: 'Enter first name',
      value: 'erdemc',
      required: true,
      validators: [
        { type: 'required', message: 'First name is required' },
        { type: 'minLength', value: 2, message: 'Minimum 2 characters required' }
      ],
      gridSize: 6,
      order: 1
    },
    {
      key: 'lastName',
      type: 'text',
      label: 'Last Name',
      placeholder: 'Enter last name',
      required: true,
      validators: [
        { type: 'required', message: 'Last name is required' }
      ],
      gridSize: 12,
      order: 2
    },
    {
      key: 'email',
      type: 'email',
      label: 'Email Address',
      placeholder: 'Enter email',
      required: true,
      validators: [
        { type: 'required', message: 'Email is required' },
        { type: 'email', message: 'Please enter a valid email' }
      ],
      order: 3
    },
    {
      key: 'userType',
      type: 'select',
      label: 'User Type',
      required: true,
      options: [
        { key: 'admin', value: 'Administrator' },
        { key: 'user', value: 'Regular User' },
        { key: 'guest', value: 'Guest User' }
      ],
      validators: [
        { type: 'required', message: 'Please select user type' }
      ],
      order: 4
    },
    {
      key: 'adminNotes',
      type: 'textarea',
      label: 'Admin Notes',
      placeholder: 'Enter admin-specific notes',
      conditionalLogic: [
        {
          dependsOn: 'userType',
          condition: 'equals',
          value: 'admin',
          action: 'show'
        }
      ],
      order: 5
    }
  ];
      <abp-dynamic-form [fields]="formFields">
      </abp-dynamic-form>

@fahrigedik
Copy link
Member

Thanks for contributions. feature is very good but support for nested forms should be added.

@erdemcaygor erdemcaygor requested a review from Copilot October 14, 2025 14:51
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces a new dynamic form component for the ABP Angular framework that allows developers to create forms dynamically using configuration objects. The component supports various field types, validation, conditional logic, and custom components.

  • Adds a comprehensive dynamic form system with support for text, email, select, checkbox, textarea, and date field types
  • Implements conditional field visibility and enablement based on other field values
  • Provides validation configuration with custom error messages and built-in Angular validators

Reviewed Changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
npm/ng-packs/tsconfig.base.json Adds TypeScript path mapping for the new dynamic-form package
npm/ng-packs/packages/components/dynamic-form/src/public-api.ts Exports public API for the dynamic form components and models
npm/ng-packs/packages/components/dynamic-form/src/dynamic-form.service.ts Service for creating form groups and handling validation logic
npm/ng-packs/packages/components/dynamic-form/src/dynamic-form.models.ts Type definitions for form field configuration and validation
npm/ng-packs/packages/components/dynamic-form/src/dynamic-form.component.ts Main dynamic form component with conditional logic and form management
npm/ng-packs/packages/components/dynamic-form/src/dynamic-form.component.scss Styling for the dynamic form layout
npm/ng-packs/packages/components/dynamic-form/src/dynamic-form.component.html Template for rendering dynamic form fields and actions
npm/ng-packs/packages/components/dynamic-form/src/dynamic-form-field/index.ts Barrel export for form field components
npm/ng-packs/packages/components/dynamic-form/src/dynamic-form-field/dynamic-form-field.component.ts Individual form field component with validation and error handling
npm/ng-packs/packages/components/dynamic-form/src/dynamic-form-field/dynamic-form-field.component.scss Styling for individual form fields
npm/ng-packs/packages/components/dynamic-form/src/dynamic-form-field/dynamic-form-field.component.html Template for rendering different field types
npm/ng-packs/packages/components/dynamic-form/src/dynamic-form-field/dynamic-form-field-host.component.ts Host component for dynamic custom field components
npm/ng-packs/packages/components/dynamic-form/ng-package.json Package configuration for the dynamic form library
npm/ng-packs/apps/dev-app/src/server.ts Removes conditional check for TLS rejection in development
npm/ng-packs/apps/dev-app/src/app/home/home.component.ts Adds example usage of the dynamic form component
npm/ng-packs/apps/dev-app/src/app/home/home.component.html Updates template to include dynamic form demonstration

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

const validator = this.field().validators.find(
v => v.type.toLowerCase() === key.toLowerCase(),
);
console.log(this.field().validators, key);
Copy link

Copilot AI Oct 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove console.log statement used for debugging. This should not be present in production code.

Suggested change
console.log(this.field().validators, key);

Copilot uses AI. Check for mistakes.
}

submit() {
console.log(this.dynamicForm.valid, this.dynamicForm.value);
Copy link

Copilot AI Oct 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove console.log statement used for debugging. This should not be present in production code.

Suggested change
console.log(this.dynamicForm.valid, this.dynamicForm.value);

Copilot uses AI. Check for mistakes.
return `Maximum length is ${this.control.errors[key].requiredLength}`;
return `${this.field().label} is invalid due to ${key} validation.`;
});
}
Copy link

Copilot AI Oct 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The errors getter method doesn't return anything when there are no errors. It should return an empty array to ensure consistent return type.

Suggested change
}
}
return [];

Copilot uses AI. Check for mistakes.
if (environment.production === false) {
process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = "0";
}
process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = "0";
Copy link

Copilot AI Oct 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting NODE_TLS_REJECT_UNAUTHORIZED to '0' disables TLS certificate validation globally, which is a security risk. This should be conditional for development environments only or use a more targeted approach.

Suggested change
process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = "0";
if (!environment.production) {
process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = "0";
}

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Angular - Dynamic Form Component

3 participants