A component for rendering UIs based on attrbiuteDefinitions
or typeDefinitions
.
What is a type definition? https://docs.commercetools.com/http-api-projects-types
What is an attribute definition? https://docs.commercetools.com/http-api-projects-productTypes#attributedefinition
This component was made taking into account some technical decisions that we will explain later on, but for good usage this component needs:
Formik
(https://github.com/jaredpalmer/formik)UIKit
(https://github.com/commercetools/ui-kit)
import { CustomFields } from '@commercetools-local/core/components/custom-fields';
<CustomFields
languages={this.props.languages}
currencies={this.props.currencies}
language={this.props.language}
fieldDefinitions={definitions}
values={attributesValues}
errors={formikProps.errors}
onChange={formikProps.handleChange}
onBlur={formikProps.handleBlur}
/>
Props | Type | Required | Description |
---|---|---|---|
languages | Array | ✅ | languages for the localized inputs |
currencies | Array | ✅ | currencies for the money types |
language | String | ✅ | language for localized inputs |
fieldDefinitions | Array | ✅ | Definitions for rendering inputs depending on the type/attribute |
values | Array | ✅ | values for the definitions |
errors | Object | - | errors in case the UI is a form |
onChange | func | - | Called with an event holding the new value. Required when input is not read only. Parent should pass it back as value - |
onBlur | func | - | Called when field is blurred |
isDisabled | bool | - | Render the component in disabled mode |
isReadOnly | bool | - | Render the component in read only mode |
- The idea here is to treat
product.attributes
as they arecustomFields
. Given this, we have a single resource requiring mapping fromattributes -> customFields
- The more resource types (e.g
Store
) we add in the API, itscustomFields
requires no mapping anymore. - The implementation is attached to the usage of
Formik
asFieldArray
plays an important role forset
types. - The component do NOT support for now nested attributes nor nested definitions (Set of sets)
- When passing the values to the component (look
values
prop), is needed to provide the whole entity containing the custom fields (eg LineItem, Order, Channel, etc). In other words, you cannot pass the values directly as the component is made under the assumption thatcustom.fields
exists.
+--------------------+ +--------------------+
| | | |
| ProductDetails | | *Details |
| | | |
+--------------------+ +--------------------+
| |
| |
| |
| |
| |
| |
+---------v----------+ +---------v----------+
| | | |
| ProductAttributes +--map to custom fields-----> CustomFields |
| | | |
+-----------------^--+ +--------------------+
| |
| |
| |
+-----map to attributes------------------+
The relation between types/attributes and UIKit inputs are:
Type | Input | Notes |
---|---|---|
text | TextInput |
In case is multiline we render MultilineTextInput |
number | NumberInput |
- |
localizedstring, ltext | LocalizedTextInput |
In case is multiline we render LocalizedMultilineTextInput |
money | MoneyInput |
- |
boolean | SelectInput |
- |
enum, localizedenum, lenum | SelectInput |
- |
reference | TextInput |
In case the resource is for a category we use an AsyncSelectInput |
time | TimeInput |
- |
datetime | DateTimeInput |
- |
date | DateInput |
- |
In the case of set
types we use a combination of the inputs above with FieldArray
from Formik for handling array values. The only exception is for set
of localizedstring, ltext
as its designs is WIP.
This component also contains two utilities that are needed in case we want:
Conversions (required)
import { parseCustomFieldsValues } from '@commercetools-local/core/components/custom-fields';
...
...
this.props.orderUpdater.execute(formValuesToDoc(parseCustomFieldsValues(orderDraft)))
Specific conversions are needed specially for the set types so the empty values are filtered out when sending the request to CTP.
Validation (optional)
import { validateCustomFields } from '@commercetools-local/core/components/custom-fields';
....
....
<Formik
validate={formValues => validateCustomFields(formValues, this.props.language)}
...
/>
This component is now present in:
- Orders custom fields tab
- Orders Line Items modal (custom fields and attributes)
- Customers custom fields tab
- Channels custom fields tab
- Categories custom fields
- Product attributes (variant attributes)
- Price Custom fields
- Add this component to
application-kit
so user can reuse this for custom applications - Add animation for expanding/collapse array values
- Render
boolean
types with checkboxes instead of withSelectInput
- Add unit tests
- Add integration test