Recipes
Recipes are copy-pasteable starting points as examples
Each one is a complete, single-file component.
The examples below keep their CSS in an inline
<style>block so each one can be pasted and run on its own. In real screens, define your styles in the platform's styling feature instead and keep only the class names in your component.
A simple editor widget
Wraps LabeledEditor, edits one value, keeps no local state for data.
import React from "react";
import LabeledEditor from "components/editors/LabeledEditor";
function TextEditor(props) {
const { data, onChange, valueType } = props;
const isNumeric = valueType === "integer" || valueType === "number";
const handleChange = (e) => {
let value = e.target.value;
if (value === "") value = undefined;
else if (valueType === "integer") {
const parsed = parseInt(value, 10);
value = isNaN(parsed) ? undefined : parsed;
} else if (valueType === "number") {
const parsed = Number(value);
value = isNaN(parsed) ? undefined : parsed;
}
onChange(value);
};
return (
<LabeledEditor {...props}>
<input
className="Rie-input Rie-input-text"
type={isNumeric ? "number" : "text"}
value={data === undefined ? "" : data}
onChange={handleChange}
{...(valueType === "number" && { step: "any" })}
{...(valueType === "integer" && { step: "1" })}
/>
</LabeledEditor>
);
}
export default TextEditor;Three rules this follows:
no
useStatefordata, since the platform owns the value,labelis never defined; it comes from the field's schema,undefinedclears the value, which removes the field from the record.
When you do need local state
Only for high-frequency input. Keep a local mirror and throttle the update:
A custom list with grouped cards
List with server-side filtering and paging
A custom list receives the whole result set, so drive paging yourself through onFilter:
A custom editor
Two things to notice: props.events() is a function call and the onSave it returns takes no arguments: it reads the record and the changes itself, and runs validation.
Reusing the standard editors
Your sections and layout, the platform's field editors:
A custom page that fetches its own data
Custom pages get no data by default. Two options.
Option A: query directly
For a filtered query, remember the versionId so results refresh after a save:
Option B: get the standard data contract
This needs props.schema, so configure the menu entry to use the UI definition for that type.
Calling the backend directly
When the standard record operations aren't enough:
For a file, use global.downloadWrapper(url) instead. It handles the filename and the save dialog.
Translations, icons, tooltips, conditions
Expressions, including lookups
Synchronous, no context needed:
Asynchronous, when the expression fetches another record:
Remembering UI state per user
Using an npm package
esm.sh/... with no https://. The package is downloaded when your code is compiled and bundled into your component, so prefer a platform module when one will do.
Last updated
