UNPKG

@adaptabletools/adaptable

Version:

Powerful data-agnostic HTML5 AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements

102 lines (101 loc) 4.41 kB
import * as React from 'react'; import { Select } from '../../../components/Select'; import { runIfNotResolvedIn } from '../../../Utilities/runIfNotResolvedIn'; import { useAdaptable } from '../../AdaptableContext'; import { useCallback } from 'react'; export const PermittedValuesSelector = function (props) { const adaptable = useAdaptable(); const [refetchKey, setRefetchKey] = React.useState(0); const [isLoading, setIsLoading] = React.useState(true); const [options, setOptions] = React.useState([]); const searchFilterRef = React.useRef(''); const [searchValueWasUsedWhenFiltering, setSearchValueWasUsedWhenFiltering] = React.useState(false); const dataType = React.useMemo(() => { return adaptable.api.columnApi.getColumnDataTypeForColumnId(props.columnId); }, [props.columnId]); React.useEffect(() => { if (!props.columnId) { setIsLoading(false); return; } setIsLoading(true); (async () => { let searchValueUsedInFilterValue = false; const currentSearchValue = searchFilterRef.current; const distinctColumnValues = await runIfNotResolvedIn( // we are here ALWAYS getting Filter values but sometimes we want to get other things!!! props.loadValues ? props.loadValues({ get currentSearchValue() { searchValueUsedInFilterValue = true; return currentSearchValue; }, }) : adaptable.api.gridApi.internalApi.getDistinctFilterDisplayValuesForColumn({ columnId: props.columnId, get currentSearchValue() { searchValueUsedInFilterValue = true; return currentSearchValue; }, }), () => { setIsLoading(true); }); setSearchValueWasUsedWhenFiltering(searchValueUsedInFilterValue); setIsLoading(false); setOptions(distinctColumnValues); })(); }, [props.columnId, props.loadValues, refetchKey]); const isCreatable = (props.allowNewValues && !dataType) || ['text', 'number'].includes(dataType); const handleSingleValueChange = (value) => { if (isCreatable) { // try to convert to correct type, when there is not type, e.g. field if (!dataType && typeof value === 'string' && !isNaN(parseFloat(value))) { props.onChange(parseFloat(value)); } else if (dataType === 'number') { let num = parseFloat(value); num = isNaN(num) ? null : num; props.onChange(num); } else { props.onChange(value); } } else { props.onChange(value); } }; const handleMultiValueChange = (values) => { if (isCreatable) { if (dataType === 'number') { const nums = values.map((v) => parseFloat(v)).filter((v) => !isNaN(v)); props.onChange(nums); } else { props.onChange(values); } } else { props.onChange(values); } }; const handleOnChange = (value) => { // convert numbers if (props.isMulti) { handleMultiValueChange(value); } else { handleSingleValueChange(value); } }; const reload = useCallback(() => { setRefetchKey((k) => k + 1); }, []); const onInputChange = (value) => { searchFilterRef.current = value; if (searchValueWasUsedWhenFiltering) { reload(); } }; return (React.createElement(Select, { menuPortalTarget: props.menuPortalTarget, size: props.size, isMulti: props.isMulti, className: props.className, disabled: props.disabled, closeMenuOnSelect: !props.isMulti, "data-name": "permitted-values-selector", placeholder: props.placeholder || (props.allowNewValues ? 'Select or type new value' : 'Select value'), isCreatable: isCreatable, isClearable: true, onMenuOpen: reload, options: options, isLoading: isLoading, onInputChange: onInputChange, onChange: handleOnChange, onFocus: props.onFocus, onBlur: props.onBlur, value: props.value })); };