@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
JavaScript
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 }));
};