Skip to content

Dropdown Form Control

Show dropdown with database data

let dbMasterConfig: T.IDBMasterConfig = {
    form: {
        fields: [
            [{
                label: 'Person',
                control: T.EDBMasterFormControl.dropdown,
                path: 'person_id',
                dropdownSettings: {
                    showClear: true,

                    dataSource: 'db_data',
                    dbData: { // Optional, it can pickup instance,database,collection details from schema.
                        collection: 'persons',
                        select: 'person_name, mobile_no, _id'
                    },
                    optionLabel: 'person_name', // 👈 It will be displayed in UI, HTML supported
                    optionValue: '_id', // 👈 It will be saved in database.

                    filter: true,
                    filterBy: 'person_name,mobile_no,_id',
                    // filterBy: 'person_name',
                    filterMatchMode: 'contains',
                    // virtualScroll: false,
                    alwaysGetLatestDataOnFormOpen: true,
                },
                validations: {
                    required: true,
                }
            }]
        ]
    }
};

Show static data

let dbMasterConfig: T.IDBMasterConfig = {
    form: {
        fields: [
            [{
                label: 'Gender',
                control: T.EDBMasterFormControl.dropdown,
                path: 'gender',
                dropdownSettings: {
                    showClear: true,

                    dataSource: 'static_data',
                    staticData: [{
                        label: 'Male', // Shown In UI
                        value: 'male', // Saved In DB
                        data: 'some other property data 1',
                    }, {
                        label: 'Female',
                        value: 'female',
                        data: 'some other property data 1',
                    }],
                    optionLabel: 'label', // 👈 It will be displayed in UI, HTML supported
                    optionValue: 'value', // 👈 It will be saved in database.

                    filter: true,
                    filterBy: 'label',
                    filterMatchMode: 'contains',
                },
                validations: {
                    required: true,
                }
            }]
        ]
    }
};

Show data from custom API

let dbMasterConfig: T.IDBMasterConfig = {
    form: {
        fields: [
            [{
                label: 'Cities',
                control: T.EDBMasterFormControl.dropdown,
                path: 'city_id',

                dropdownSettings: {
                    dataSource: 'api_call',
                    optionLabel: 'city_name',
                    optionValue: '_id',
                    apiCallOverrides: {
                        // :userPath = it will be replaced with admin user path by master page automatically.
                        // :beHostPort = it will be replaced with API Maker backend's protocol and host and port automatically. ex : https://example.com
                        // url: ':beHostPort/api/custom-api/:userPath/list-of-cities', // 👈 Use this to make it dynamic
                        url: 'http://localhost:38246/api/custom-api/admin/list-of-cities',
                    },
                    jsCode: [{
                        appendTo: T.EDBMasterDropdownAppendTo.modifyDropdownRequest,
                        code: `
                            reqBody.state_id = formData.state_id;
                            console.log(body);
                        `
                    }],
                },
            }]
        ]
    }
};

Add new item support

let dbMasterConfig: T.IDBMasterConfig = {
    form: {
        fields: [
            [{
                label: 'Product Categories',
                control: T.EDBMasterFormControl.dropdown,
                path: 'product_category_id',
                dropdownSettings: {
                    showClear: true,

                    dataSource: 'db_data',
                    dbData: {
                        collection: 'product_categories',
                        select: 'name'
                    },
                    optionLabel: 'name',
                    optionValue: '_id',

                    addNewFormConfig: { // 👈 Opens add product category & saves & reloads dropdown
                        screenName: 'Product Category',
                        form: {
                            width: '500px',
                            fields: [
                                [{ // field
                                    label: 'Name',
                                    control: T.EDBMasterFormControl.input,
                                    path: 'name',
                                }]
                            ]
                        }
                    }
                },
                validations: {
                    required: true,
                }
            }]
        ]
    }
};

Dependent Dropdowns | Auto Completes | Multi Selects

👉 It supports N level of dependent dropdowns with any type of complexity.

let dbMasterConfig: T.IDBMasterConfig = {
    form: {
        fields: [
            [{
                path: 'planetId',
                control: T.EDBMasterFormControl.dropdown,

                dropdownSettings: {
                    showClear: true,
                    dataSource: 'db_data',
                    dbData: {
                        collection: 'ui_maker_planet',
                    },
                    optionValue: '_id',
                    optionLabel: 'name',

                    reloadDropdownsOfPath: ['continentId'], // 👈 dropdown | auto complete | multi select path
                },
            }],
            [{
                path: 'continentId',
                control: T.EDBMasterFormControl.dropdown,

                dropdownSettings: {
                    showClear: true,
                    dataSource: 'db_data',
                    dbData: {
                        collection: 'ui_maker_continent',
                    },
                    optionValue: '_id',
                    optionLabel: 'name',
                    isDependentOnPath: ['planetId'],
                    reloadDropdownsOfPath: ['countryId'], // 👈 dropdown | auto complete | multi select path

                    jsCode: [{
                        appendTo: T.EDBMasterDropdownAppendTo.modifyDropdownRequest,
                        code: `
                            reqBody.find.planetId = formData.planetId;
                        `,
                    }]
                }
            }],
            [{
                path: 'countryId',
                control: T.EDBMasterFormControl.dropdown,

                dropdownSettings: {
                    showClear: true,
                    dataSource: 'db_data',
                    dbData: {
                        collection: 'ui_maker_country',
                    },
                    optionValue: '_id',
                    optionLabel: 'name',
                    isDependentOnPath: ['continentId'],
                    reloadDropdownsOfPath: ['stateId'], // 👈 dropdown | auto complete | multi select path

                    jsCode: [{
                        appendTo: T.EDBMasterDropdownAppendTo.modifyDropdownRequest,
                        code: `
                            reqBody.find.continentId = formData.continentId;
                        `,
                    }]
                }
            }],
            [{
                path: 'stateId',
                control: T.EDBMasterFormControl.dropdown,

                dropdownSettings: {
                    showClear: true,
                    dataSource: 'db_data',
                    dbData: {
                        collection: 'ui_maker_states',
                    },
                    optionValue: '_id',
                    optionLabel: 'name',
                    isDependentOnPath: ['countryId'],

                    jsCode: [{
                        appendTo: T.EDBMasterDropdownAppendTo.modifyDropdownRequest,
                        code: `
                            reqBody.find.countryId = formData.countryId;
                        `,
                    }]
                }
            }]
        ]
    }
};

Interface Documentation

/**
 * Form field configuration for UI controls.
 * Defines the appearance, behavior, and validation of individual form inputs.
 */
export interface IDBMasterConfigFormField {
    /**
     * Unique identifier for programmatic element access.
     * Useful for dynamic field manipulation.
     */
    hiddenId?: string;
    /** Display label for the form field. */
    label?: string;

    /**
     * Help text displayed below the control.
     * Supports HTML formatting for rich content.
     */
    helpText?: string;

    /**
     * Database field path where the control value is stored.
     * Supports nested paths using dot notation.
     * @example 'name', 'address.city', 'user.contact.email'
     */
    path?: string;

    /** Type of UI control to render. */
    control?: EDBMasterFormControl;

    /**
     * CSS classes for the parent div wrapping the control.
     * @default 'col-lg mt-4 col-md-{calculated based on columns.length}'
     */
    cssClassDiv?: string;

    /**
     * Auto-focus this control when form opens.
     * @default false
     */
    autofocus?: boolean;

    /**
     * Disable the control or use expression to conditionally disable.
     * When a string is provided, it's evaluated as JavaScript.
     * @example true | false | "formData.type === 'readonly'"
     */
    disabled?: boolean | string;

    /**
     * Control visibility or use expression to conditionally show/hide.
     * When a string is provided, it's evaluated as JavaScript.
     * @default true
     * @example true | false | "formData.userRole === 'admin'"
     */
    visible?: boolean | string;

    /**
     * Nested form fields for complex layouts.
     * Enables hierarchical form structures within this field.
     */
    fields?: IDBMasterConfigFormField[][];

    /** Validation rules for this field. */
    validations?: Pick<IPropertyValidation, 'required'> & {
        /**
         * Dynamic required validation function.
         * Evaluated when form data changes to determine if field is required.
         * Note: When present, this takes precedence over static 'required' property.
         * @example "formData.type === 'individual' ? true : false"
         */
        requiredFun?: string;
    };
    /** Custom validation error messages. */
    validationErrors?: {
        /** Custom error message for required field validation. */
        required?: string;
    };

    /**
     * Dropdown (select) control configuration.
     * Supports static data, database queries, and custom API calls.
     */
    dropdownSettings?: {
        /** Inline style object (Angular style binding format). */
        style?: any;

        /** Space-separated CSS class names. */
        cssClass?: string,

        /** Placeholder text displayed when no selection is made. */
        placeholder?: string;
        /**
         * Show clear button to reset selection.
         * @default false
         */
        showClear?: boolean;
        /**
         * Data source type for dropdown options.
         * - `static_data`: Use predefined array of options
         * - `db_data`: Query database for options
         * - `api_call`: Call custom API endpoint
         */
        dataSource: 'static_data' | 'db_data' | 'api_call';

        /**
         * Static dropdown options.
         * Used when dataSource is 'static_data'.
         * @example [{ label: 'Option 1', value: 1 }, { label: 'Option 2', value: 2 }]
         */
        staticData?: any[];

        /**
         * Database query configuration for dropdown options.
         * Can inherit values from schema if field has database relationship defined.
         */
        dbData?: Partial<Pick<ICollectionIdentity, 'instance' | 'database' | 'collection' | 'table'>
            & Pick<IQueryFormat, 'find' | 'select' | 'limit' | 'deep' | 'sort'>>;

        /**
         * Property name to display in dropdown.
         * @default 'label'
         */
        optionLabel?: string;

        /**
         * Property name to use as option value.
         * @default 'value'
         */
        optionValue?: string;

        /**
         * Enable dropdown filtering.
         * @default false
         */
        filter?: boolean;

        /**
         * Fields to search when filtering.
         * Supports multiple fields (comma-separated, no spaces).
         * @example 'name', 'name,email,phone'
         */
        filterBy?: string;

        /**
         * Filter matching strategy.
         * @default 'contains'
         */
        filterMatchMode?: 'contains' | 'startsWith' | 'endsWith' | 'equals' | 'notEquals' | 'in' | 'lt' | 'lte' | 'gt' | 'gte';

        /**
         * Reload dropdown data when form opens.
         * Ensures options are always up-to-date.
         * @default false
         */
        alwaysGetLatestDataOnFormOpen?: boolean;

        /**
         * Enable virtual scrolling for large datasets.
         * Improves performance when dealing with thousands of options.
         * @default false
         */
        virtualScroll?: boolean;

        /**
         * Dependent dropdown cascade.
         * When this dropdown value changes, reload these other dropdowns.
         * @example ['city', 'area'] - Reload city and area dropdowns
         */
        reloadDropdownsOfPath?: string[];

        /**
         * Required field dependencies.
         * Dropdown only loads data when these fields have values.
         * @example ['country', 'state'] - Only load if country and state are selected
         */
        isDependentOnPath?: string[];

        /** Tooltip text displayed on hover. */
        tooltip?: string;

        /** Tooltip position relative to the element. */
        tooltipPosition?: 'left' | 'top' | 'bottom' | 'right';
        /** CSS class for tooltip styling. */
        tooltipStyleClass?: string;

        /** Custom event handlers and data transformation scripts. */
        jsCode?: {
            /**
             * Event type or lifecycle hook:
             * - modifyDropdownRequest: Before API call
             * - onceDropdownDataLoaded: After data loaded
             * - onChange: When selection changes
             *
             * Available variables:
             * - reqBody: Query object for modification
             * - formData: Complete form data
             * - dropdownData: Loaded options array
             * - reloadDropdownsOfPath: Array to trigger dependent reloads
             */
            appendTo: EDBMasterDropdownAppendTo,
            code: string | (($scope: IDBMasterUIPageUtilsScope) => any),

        }[],

        /**
         * Nested form configuration for adding new options.
         * Opens a modal to create new records that can be immediately selected.
         */
        addNewFormConfig?: IDBMasterConfig;

        /**
         * Custom API endpoint configuration.
         * Override default query API with custom endpoint and logic.
         */
        apiCallOverrides?: IDBMasterAPICallOverrides;
    };

}


/**
 * Validation rules for schema properties and form fields.
 * Define constraints that values must satisfy before being saved.
 */

export interface IPropertyValidation {
    /**
     * Field is mandatory and must have a non-null, non-empty value.
     * Applicable to all data types.
     */
    required?: boolean;
    /**
     * Minimum allowed value.
     * Applicable to: number, date
     */
    min?: number;
    /**
     * Maximum allowed value.
     * Applicable to: number, date
     */
    max?: number;
    /**
     * Minimum string/array length.
     * Applicable to: string, array
     */
    minLength?: number;
    /**
     * Maximum string/array length.
     * Applicable to: string, array
     */
    maxLength?: number;
    /**
     * Value must be unique across all records.
     * @deprecated API Maker maintains uniqueness internally.
     * Avoid using on tables with frequent updates due to performance impact.
     */
    unique?: boolean;
    /**
     * Validate email address format.
     * Applicable to: string
     */
    email?: boolean;
    /**
     * Custom validation function.
     * Return true if valid, false or error message if invalid.
     */
    validatorFun?: Function;

    /**
     * Enumeration constraint - value must be from this array.
     * @example ['active', 'inactive', 'pending']
     */
    enum?: any[];
}


export enum EDBMasterDropdownAppendTo {
    visible = 'visible',
    disabled = 'disabled',
    modifyDropdownRequest = 'modifyDropdownRequest',
    onceDropdownDataLoaded = 'onceDropdownDataLoaded',
    onChange = 'onChange',
}


/**
 * Available form control types for UI generation.
 * Each control type has specific settings and behavior.
 */
export enum EDBMasterFormControl {
    /** Single-line text input. */
    input = 'input',
    /** Numeric input with spinner buttons and formatting. */
    inputNumber = 'inputNumber',
    /** Text input with pattern-based masking (phone, SSN, etc.). */
    inputMask = 'inputMask',
    /** One-time password multi-character input. */
    inputOtp = 'inputOtp',
    /** Password input with visibility toggle and strength meter. */
    password = 'password',
    /** Date and/or time picker with calendar popup. */
    date_picker = 'date_picker',
    /** Multi-line text input. */
    textarea = 'textarea',
    /** Rich text WYSIWYG editor. */
    editor = 'editor',
    /** Binary checkbox (true/false). */
    checkbox = 'checkbox',
    /** Radio button group for single selection. */
    radio = 'radio',
    /** Color picker with multiple format support. */
    color_picker = 'color_picker',
    /** Dropdown select with single selection. */
    dropdown = 'dropdown',
    /** Autocomplete with type-ahead search. */
    auto_complete = 'auto_complete',
    /** Multi-select dropdown with chip display. */
    multi_select = 'multi_select',
    /** File upload with validation. */
    file_upload = 'file_upload',
    /** Nested data grid for one-to-many relationships. */
    grid = 'grid',
    /** Visual separator line. */
    divider = 'divider',
    /** Star-based rating input. */
    rating = 'rating',
    /** Circular dial for numeric input. */
    knob = 'knob',

    /** Collapsible accordion panels (field container). */
    accordion = 'accordion',
    /** Tabbed view for organizing fields (field container). */
    tab_view = 'tab_view',

    /** Clickable button with custom actions. */
    button = 'button',
    /** Image display with preview. */
    image = 'image',
    /** Custom HTML content. */
    customHTML = 'customHTML',
}

export enum EDBMasterCustomActionButtonAppendTo {
    click = 'click',
}