AI Skill Report Card

Generating Ant Select Components

B+78·May 7, 2026·Source: Web

Quick Start

Provide the entity name in kebab-case (e.g., banco, centro-custo, sindicato) and I'll generate both the model and component files with all required functionality.

Workflow

  1. Entity Identification

    • Check attachments for typings.d.ts or entity definitions
    • Analyze editor context for namespace like Planejamento.Cadastro.Area
    • Extract entity name from user request
  2. Generate Model (src/models/selects/select-<entidade>.ts)

    • Import specific controller for the entity
    • Set appropriate order_by field
    • Include addMissedOptions, getOptions, getOptionsNewPage
  3. Generate Component (src/components/selects/select-<entidade>.tsx)

    • Connect to entity-specific model via useModel('selects.select-<entidade>')
    • Configure API endpoint for search
    • Set label mapping (simple r.label or composite)

Progress:

  • Identify entity name and controller
  • Generate model file
  • Generate component file
  • Verify all placeholders replaced

Examples

Example 1: Input: "Create select for sindicato entity" Output:

TypeScript
// src/models/selects/select-sindicato.ts import { getSindicatosController } from '@/services/global/sindicato.controller'; // ... (complete model with getSindicatosController) // src/components/selects/select-sindicato.tsx const { ... } = useModel('selects.select-sindicato'); // ... (complete component with '/api/pessoal/sindicatos/')

Example 2: Input: "Generate select for colaborador with composite label" Output:

TypeScript
// Label mapping in component: label: `${r.codigo} - ${r.nome}` // order_by: 'codigo' instead of 'label'

Model Template

TypeScript
import { defaultPaginationValues } from '@/constants/pagination'; import useLoading from '@/hooks/use-loading'; import { getUpdateSelectOptions } from '@/utils/get-update-select-options'; import { message } from 'antd'; import { useState } from 'react'; import { get<Entity>Controller } from '<controller-path>'; export default () => { const [options, setOptions] = useState<App.Pagination<any>>(defaultPaginationValues); const [queryStringOptionsParams, setQueryStringOptionsParams] = useState<App.QueryStringParams>({ page: 1, page_size: 10, order_by: 'label', // or 'codigo' for composite labels }); const { loading, startLoading, stopLoading } = useLoading(); const addMissedOptions = async (ids: number[]) => { try { startLoading(); const params: App.QueryStringParams = { ...queryStringOptionsParams, page: 1, page_size: 1000, id: ids, }; const response = await get<Entity>Controller(params); const { data } = response; setOptions((previousData) => { const results: any[] = getUpdateSelectOptions(data.results, previousData.results); return { ...previousData, results }; }); } catch (error) { message.error('Não foi possível obter os dados'); } finally { stopLoading(); } }; // ... getOptions and getOptionsNewPage methods return { selectLoading: loading, addMissedOptions, options, getOptions, getOptionsNewPage, queryStringOptionsParams, }; };

Component Template

TypeScript
import { useModel } from '@umijs/max'; import { Select, SelectProps } from 'antd'; import { debounce } from 'lodash'; import { useEffect, useMemo, useState } from 'react'; interface Props { value?: any; onChange?: (val: any, option: any) => void; multiple?: boolean; allowClear?: boolean; style?: any; placeholder?: string; disabled?: boolean; labelInValue?: boolean; isInstanceForColumnFilter?: boolean; } export default (props: Props) => { const [needFillMissedOptions, setNeedFillMissedOptions] = useState<boolean>(true); const [searchValue, setSearchValue] = useState<string>(); const [isSearching, setIsSearching] = useState<boolean>(false); const { selectLoading, options, getOptions, getOptionsNewPage, queryStringOptionsParams, addMissedOptions, } = useModel('selects.select-<entity>'); // Debounced search with getSelectController('<API_ENDPOINT>', params) const debouncedSearch = useMemo(() => debounce((value: string) => { if (value) { setIsSearching(true); // Search logic with API endpoint } else { setIsSearching(false); } }, 700), []); // Options mapping: r.label or `${r.codigo} - ${r.nome}` const optionsMemo = useMemo(() => { return (options.results || []).map((r: any) => ({ label: r.label, // or composite label value: r.id, })); }, [options.results]); // Fill missing options on mount useEffect(() => { // addMissedOptions logic for pre-filled values }, [value]); return ( <Select searchValue={searchValue} onSearch={(value) => { setSearchValue(value); debouncedSearch(value); }} options={isSearching ? optionsSearched : optionsMemo} placeholder={props.placeholder || 'Selecione'} showSearch onPopupScroll={handleScroll} loading={selectLoading} value={props.value} onChange={props.onChange} mode={props.multiple ? 'multiple' : undefined} allowClear={props.allowClear} disabled={props.disabled} labelInValue={props.labelInValue} // ... other props /> ); };

Best Practices

  • Always create separate models: Each entity gets its own model file, never share generic models
  • Use correct useModel key: Format is always 'selects.select-<entity>'
  • Set appropriate order_by: Use 'label' for simple labels, 'codigo' for composite ones
  • Configure API endpoint: Replace 'ENDPOINT_AQUI' with actual API path
  • Handle missing options: addMissedOptions ensures pre-filled values display correctly
  • Debounce search: 700ms delay prevents excessive API calls

Common Pitfalls

  • Don't create generic shared models - each entity needs its own
  • Don't forget to replace placeholder controller imports
  • Don't use wrong useModel key format
  • Don't miss API endpoint configuration for search functionality
  • Don't forget label mapping in options memo

Placeholder Replacements

PlaceholderReplace WithExample
<entity>Entity name in kebab-casesindicato, centro-custo
get<Entity>ControllerActual controller functiongetSindicatosController
<controller-path>Controller import path@/services/global/sindicato.controller
'<API_ENDPOINT>'API endpoint string'/api/pessoal/sindicatos/'
r.labelLabel mappingr.label or ${r.codigo} - ${r.nome}
0
Grade B+AI Skill Framework
Scorecard
Criteria Breakdown
Quick Start
13/15
Workflow
13/15
Examples
15/20
Completeness
20/20
Format
15/15
Conciseness
12/15