UNPKG

ra-core

Version:

Core components of react-admin, a frontend Framework for building admin applications on top of REST services, using ES6, React

115 lines 4.66 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.useUnique = void 0; const react_1 = require("react"); const merge_js_1 = __importDefault(require("lodash/merge.js")); const set_js_1 = __importDefault(require("lodash/set.js")); const core_1 = require("../../core/index.cjs"); const dataProvider_1 = require("../../dataProvider/index.cjs"); const i18n_1 = require("../../i18n/index.cjs"); const util_1 = require("../../util/index.cjs"); const controller_1 = require("../../controller/index.cjs"); const validate_1 = require("./validate.cjs"); /** * A hook that returns a validation function checking for a record field uniqueness * by calling the dataProvider getList function with a filter. * * @example // Passing options at declaration time * const UserCreateForm = () => { * const unique = useUnique({ message: 'Username is already used'}); * return ( * <SimpleForm> * <TextInput source="username" validate={unique()} /> * </SimpleForm> * ); * } * * @example // Passing options at call time * const UserCreateForm = () => { * const unique = useUnique(); * return ( * <SimpleForm> * <TextInput source="username" validate={unique({ message: 'Username is already used'})} /> * </SimpleForm> * ); * } * * @example // With additional filters * const UserCreateForm = () => { * const unique = useUnique(); * return ( * <SimpleForm> * <ReferenceInput source="organization_id" reference="organizations" /> * <FormDataConsumer> * {({ formData }) => ( * <TextInput * source="username" * validate={unique({ filter: { organization_id: formData.organization_id })} * /> * )} * </FormDataConsumer> * </SimpleForm> * ); * } */ const useUnique = (options) => { const dataProvider = (0, dataProvider_1.useDataProvider)(); const translateLabel = (0, i18n_1.useTranslateLabel)(); const resource = (0, core_1.useResourceContext)(options); if (!resource) { throw new Error('useUnique: missing resource prop or context'); } const translate = (0, i18n_1.useTranslate)(); const record = (0, controller_1.useRecordContext)(); const debouncedGetList = (0, react_1.useRef)( // The initial value is here to set the correct type on useRef (0, util_1.asyncDebounce)(dataProvider.getList, options?.debounce ?? DEFAULT_DEBOUNCE)); const validateUnique = (0, react_1.useCallback)((callTimeOptions) => { const { message, filter, debounce: interval, } = (0, merge_js_1.default)({ debounce: DEFAULT_DEBOUNCE, filter: {}, message: 'ra.validation.unique', }, options, callTimeOptions); debouncedGetList.current = (0, util_1.asyncDebounce)(dataProvider.getList, interval); return async (value, allValues, props) => { if ((0, validate_1.isEmpty)(value)) { return undefined; } try { const finalFilter = (0, set_js_1.default)((0, merge_js_1.default)({}, filter), props.source, value); const { data, total } = await debouncedGetList.current(resource, { filter: finalFilter, pagination: { page: 1, perPage: 1 }, sort: { field: 'id', order: 'ASC' }, }); if (typeof total !== 'undefined' && total > 0 && !data.some(r => r.id === record?.id)) { return { message, args: { source: props.source, value, field: translateLabel({ label: props.label, source: props.source, resource, }), }, }; } } catch (error) { return translate('ra.notification.http_error'); } return undefined; }; }, [dataProvider, options, record, resource, translate, translateLabel]); return validateUnique; }; exports.useUnique = useUnique; const DEFAULT_DEBOUNCE = 1000; //# sourceMappingURL=useUnique.js.map