Template field editors
The templateFields object is a supported web store named export that Sana expects an add-on to provide from its entry JavaScript module.
It's an object with the signature described below, whose property names are the template field editor names and property values are objects with instances of the React components, responsible for rendering of the corresponding editors for template fields.
templateFields?: Record<string,
| {
editor: TemplateFieldEditor;
}
| {
display: ReadOnlyTemplateFieldEditor;
}>;
Example:
import type { AddonExports } from 'sana/types';
import DeliveryDateEditor from 'components/DeliveryDateEditor';
import DeliveryDateDisplay from 'components/DeliveryDateDisplay';
const addonExports: AddonExports = {
templateFields: {
MyDeliveryDateEditor: {
editor: DeliveryDateEditor,
},
MyDeliveryDateEditorReadOnly: {
display: DeliveryDateDisplay,
},
},
};
export default addonExports;
TemplateFieldEditor component
The TemplateFieldEditor is react component to manage template field value.
It expects the properties of TemplateFieldEditorProps<S = any> type where S is the type of editor settings.
The TemplateFieldEditorProps<S = any> type contains the following properties:
| Property | Type | Description |
|---|---|---|
| fieldName | string | The field form name. |
| fieldTitle | string | The field title. |
| description | string | null | The field description. |
| settings | S = any | The editor settings. |
| initialValue | any | The initial field value. |
| disabled | boolean | The value indicating whether the field is disabled. |
| required | boolean | The value indicating whether the field value is required. |
| validation | Validation | Object with field value validation rules. |
The Validation type contains the following properties:
| Property | Type | Description |
|---|---|---|
| required | (optional) boolean | Enables validation that field is mandatory. |
| custom | (optional) (value: any) => string | null | undefined | Custom validation function which returns undefined in case validation succeeded, nullable error message otherwise. |
Example:
import type { TemplateFieldEditor } from 'sana/templateFields';
import { useMemo, useCallback } from 'react';
import { FormGroup, FieldLabel, DatePickerField } from 'sana/forms';
import { useSimpleTexts } from 'sana/texts';
type Settings = {
availabilityInDays: number;
notAvailableDates: string[] | null;
};
const DeliveryDateEditor: TemplateFieldEditor<Settings> = ({
fieldName,
fieldTitle,
description,
settings,
initialValue,
disabled,
required,
validation,
}) => {
const { texts: [validationDateIsNotAvailableMessage] } = useSimpleTexts(['ValidationDateIsNotAvailable']);
const minDate = useMemo(() => {
const date = new Date();
date.setHours(0, 0, 0, 0);
date.setDate(date.getDate() + settings.availabilityInDays);
return date;
}, [settings.availabilityInDays]);
const deliveryDateValidation = useMemo(() => {
if (!validationDateIsNotAvailableMessage || !settings.notAvailableDates?.length)
return validation;
const notAvailableDates = settings.notAvailableDates.map(s => getDateHash(new Date(s)));
return {
...validation,
custom(value: any) {
if (validation.custom) {
const validationResult = validation.custom(value);
if (validationResult !== undefined)
return validationResult;
}
if (!value)
return;
const hash = getDateHash(new Date(value));
return notAvailableDates.includes(hash) ? validationDateIsNotAvailableMessage : undefined;
},
};
}, [validation, validationDateIsNotAvailableMessage, settings.notAvailableDates]);
const isDateAvailable = useCallback((date: Date) => deliveryDateValidation.custom!(date) === undefined, [deliveryDateValidation]);
const label = (
<FieldLabel
fieldName={fieldName}
required={required}
focusToFieldOnClick
>
{fieldTitle}
</FieldLabel>
);
const field = (
<DatePickerField
fieldName={fieldName}
fieldTitle={fieldTitle}
initialValue={initialValue}
required={required}
disabled={disabled}
minDate={minDate}
validation={deliveryDateValidation}
isDateAvailable={isDateAvailable}
/>
);
return (
<FormGroup
label={label}
field={field}
description={description}
/>
);
};
export default DeliveryDateEditor;
function getDateHash(date: Date) {
const year = date.getFullYear();
const month = date.getMonth() + 1;
const day = date.getDate();
return `${year}-${month}-${day}`;
}
ReadOnlyTemplateFieldEditor component
The ReadOnlyTemplateFieldEditor is react component to display template field read only value.
It expects the properties of ReadOnlyTemplateFieldEditorProps<S = any> type where S is the type of editor settings.
The ReadOnlyTemplateFieldEditorProps<S = any> type contains the following properties:
| Property | Type | Description |
|---|---|---|
| fieldName | string | The field form name. |
| fieldTitle | string | The field title. |
| description | string | null | The field description. |
| settings | S = any | The editor settings. |
| value | any | The field value. |
| displayValue | string | null | The formatted field value. |
Example:
import type { ReadOnlyTemplateFieldEditor } from 'sana/templateFields';
import { ReadOnlyFormGroup, FieldLabel } from 'sana/forms';
import { DateDisplay } from 'sana/elements';
type Settings = {
longFormat: boolean;
};
const DeliveryDateDisplay: ReadOnlyTemplateFieldEditor<Settings> = ({
fieldName,
fieldTitle,
description,
settings,
value,
}) => {
const field = <DateDisplay value={value} longFormat={settings.longFormat} />;
const label = <FieldLabel fieldName={fieldName}>{fieldTitle}</FieldLabel>;
return (
<ReadOnlyFormGroup
label={label}
field={field}
description={description}
/>
);
};
export default DeliveryDateDisplay;