diff --git a/demo/collections/CustomComponents/components/fields/Select/Field/index.tsx b/demo/collections/CustomComponents/components/fields/Select/Field/index.tsx index f5ca7cdb96..5ae50e17ea 100644 --- a/demo/collections/CustomComponents/components/fields/Select/Field/index.tsx +++ b/demo/collections/CustomComponents/components/fields/Select/Field/index.tsx @@ -1,6 +1,7 @@ -import React, { useState } from 'react'; +import React, { useCallback, useState } from 'react'; import SelectInput from '../../../../../../../src/admin/components/forms/field-types/Select'; import { Props as SelectFieldType } from '../../../../../../../src/admin/components/forms/field-types/Select/types'; +import useFieldType from '../../../../../../../src/admin/components/forms/useFieldType'; const Select: React.FC = (props) => { const { @@ -10,16 +11,43 @@ const Select: React.FC = (props) => { options } = props; - const [internalValue, setInternalValue] = useState(''); + const { + value, + setValue + } = useFieldType({ + path + }); + + const onChange = useCallback((incomingValue) => { + const sendToCRM = async () => { + try { + const req = await fetch('https://fake-crm.com', { + method: 'post', + body: JSON.stringify({ + someKey: incomingValue + }) + }); + + const res = await req.json(); + if (res.ok) { + console.log('Successfully synced to CRM.') + } + } catch (e) { + console.error(e); + } + } + + sendToCRM(); + setValue(incomingValue) + }, []) return ( ) }; diff --git a/demo/collections/CustomComponents/components/fields/Text/Field/index.tsx b/demo/collections/CustomComponents/components/fields/Text/Field/index.tsx index b5af293cdc..2c8d2bdb71 100644 --- a/demo/collections/CustomComponents/components/fields/Text/Field/index.tsx +++ b/demo/collections/CustomComponents/components/fields/Text/Field/index.tsx @@ -1,6 +1,7 @@ import React, { useCallback, useState } from 'react'; import TextInput from '../../../../../../../src/admin/components/forms/field-types/Text'; import { Props as TextFieldType } from '../../../../../../../src/admin/components/forms/field-types/Text/types'; +import useFieldType from '../../../../../../../src/admin/components/forms/useFieldType'; const Text: React.FC = (props) => { const { @@ -9,19 +10,24 @@ const Text: React.FC = (props) => { label } = props; - const [internalValue, setInternalValue] = useState(''); + const { + value, + setValue + } = useFieldType({ + path + }); - const middleware = useCallback((incomingValue) => { - setInternalValue(`Hello, world: ${incomingValue}`) + const onChange = useCallback((incomingValue) => { + const valueWithoutSpaces = incomingValue.replace(/\s/g, ''); + setValue(valueWithoutSpaces) }, []) return ( ) }; diff --git a/demo/collections/CustomComponents/components/fields/UI/Field/index.tsx b/demo/collections/CustomComponents/components/fields/UI/Field/index.tsx new file mode 100644 index 0000000000..dd56f4d6f7 --- /dev/null +++ b/demo/collections/CustomComponents/components/fields/UI/Field/index.tsx @@ -0,0 +1,50 @@ +import React, { useCallback } from 'react'; +import TextInput from '../../../../../../../src/admin/components/forms/field-types/Text'; +import { UIField as UIFieldType } from '../../../../../../../src/fields/config/types'; +import SelectInput from '../../../../../../../src/admin/components/forms/field-types/Select'; + +const UIField: React.FC = () => { + const [textValue, setTextValue] = React.useState(''); + const [selectValue, setSelectValue] = React.useState(''); + + const onTextChange = useCallback((incomingValue) => { + setTextValue(incomingValue); + }, []) + + const onSelectChange = useCallback((incomingValue) => { + setSelectValue(incomingValue); + }, []) + + return ( +
+ + +
+ ) +}; + +export default UIField; diff --git a/demo/collections/CustomComponents/components/fields/Upload/Field/index.tsx b/demo/collections/CustomComponents/components/fields/Upload/Field/index.tsx index 6fe6a546bd..9f6d00d29e 100644 --- a/demo/collections/CustomComponents/components/fields/Upload/Field/index.tsx +++ b/demo/collections/CustomComponents/components/fields/Upload/Field/index.tsx @@ -1,6 +1,7 @@ -import React, { useState } from 'react'; +import React, { useCallback, useState } from 'react'; import Upload from '../../../../../../../src/admin/components/forms/field-types/Upload'; import { Props as UploadFieldType } from '../../../../../../../src/admin/components/forms/field-types/Upload/types'; +import useFieldType from '../../../../../../../src/admin/components/forms/useFieldType'; const Text: React.FC = (props) => { const { @@ -11,17 +12,25 @@ const Text: React.FC = (props) => { fieldTypes } = props; - const [internalValue, setInternalValue] = useState(''); + const { + value, + setValue + } = useFieldType({ + path + }); + + const onChange = useCallback((incomingValue) => { + setValue(incomingValue) + }, []) return ( ) }; diff --git a/demo/collections/CustomComponents/index.ts b/demo/collections/CustomComponents/index.ts index 495b78a563..e09ef5ae1f 100644 --- a/demo/collections/CustomComponents/index.ts +++ b/demo/collections/CustomComponents/index.ts @@ -9,6 +9,7 @@ import NestedArrayField from './components/fields/NestedArrayCustomField/Field'; import GroupField from './components/fields/Group/Field'; import NestedGroupField from './components/fields/NestedGroupCustomField/Field'; import NestedText1Field from './components/fields/NestedText1/Field'; +import UIField from './components/fields/UI/Field'; import ListView from './components/views/List'; import CustomDescriptionComponent from '../../customComponents/Description'; @@ -30,7 +31,7 @@ const CustomComponents: CollectionConfig = { }, { name: 'text', - label: 'Text', + label: 'Custom text field (removes whitespace)', type: 'text', required: true, localized: true, @@ -42,7 +43,7 @@ const CustomComponents: CollectionConfig = { }, { name: 'select', - label: 'Select', + label: 'Custom select field (sends value to crm)', type: 'select', localized: true, options: [ @@ -65,6 +66,16 @@ const CustomComponents: CollectionConfig = { }, }, }, + { + name: 'ui', + label: 'UI', + type: 'ui', + admin: { + components: { + Field: UIField, + }, + }, + }, { name: 'upload', label: 'Upload', diff --git a/src/admin/components/forms/field-types/Select/index.tsx b/src/admin/components/forms/field-types/Select/index.tsx index fb946595e6..1aa6f06b3d 100644 --- a/src/admin/components/forms/field-types/Select/index.tsx +++ b/src/admin/components/forms/field-types/Select/index.tsx @@ -54,7 +54,7 @@ const Select: React.FC = (props) => { }, [validate, required, options]); const { - value, + value: valueFromContext, showError, setValue, errorMessage, @@ -90,12 +90,6 @@ const Select: React.FC = (props) => { setValue ]) - useEffect(() => { - if (typeof valueFromProps === 'string') { - setValue(valueFromProps); - } - }, [valueFromProps]) - const classes = [ 'field-type', baseClass, @@ -105,6 +99,8 @@ const Select: React.FC = (props) => { let valueToRender; + const value = valueFromProps || valueFromContext || ''; + if (hasMany && Array.isArray(value)) { valueToRender = value.map((val) => options.find((option) => option.value === val)); } else { diff --git a/src/admin/components/forms/field-types/Text/index.tsx b/src/admin/components/forms/field-types/Text/index.tsx index d41b71f0d2..be60e6c376 100644 --- a/src/admin/components/forms/field-types/Text/index.tsx +++ b/src/admin/components/forms/field-types/Text/index.tsx @@ -38,7 +38,7 @@ const Text: React.FC = (props) => { }); const { - value, + value: valueFromContext, showError, setValue, errorMessage, @@ -46,21 +46,16 @@ const Text: React.FC = (props) => { const onChange = useCallback((e) => { const { value: incomingValue } = e.target; - setValue(e); if (typeof onChangeFromProps === 'function') { onChangeFromProps(incomingValue); + } else { + setValue(e); } }, [ onChangeFromProps, setValue, ]); - useEffect(() => { - if (typeof valueFromProps === 'string') { - setValue(valueFromProps); - } - }, [valueFromProps]) - const classes = [ 'field-type', 'text', @@ -68,6 +63,8 @@ const Text: React.FC = (props) => { readOnly && 'read-only', ].filter(Boolean).join(' '); + const value = valueFromProps || valueFromContext || ''; + return (
= (props) => { required={required} /> = (props) => { }); const { - value, + value: valueFromContext, showError, setValue, errorMessage, } = fieldType; + const value = valueFromProps || valueFromContext || ''; + const classes = [ 'field-type', baseClass, @@ -83,7 +85,6 @@ const Upload: React.FC = (props) => { setInternalValue(json); } else { setInternalValue(undefined); - setValue(null); setMissingFile(true); } }; @@ -92,7 +93,6 @@ const Upload: React.FC = (props) => { } }, [ value, - setInternalValue, relationTo, api, serverURL, @@ -108,8 +108,6 @@ const Upload: React.FC = (props) => { } }, [internalValue]); - const valueToUse = valueFromProps || value || ''; - return (
= (props) => { }} /> )} - {(!valueToUse || missingFile) && ( + {(!value || missingFile) && (