Advanced

Custom components

Add your own React component and use it in schemas by name.

registerComponent

Any React component can be used in schemas: registerComponent("Stat", Stat) and then { type: "Stat", props: { ... } }. Its props come from the node's props.

A container ({ container: true }) receives node and renderNodes; draw the children with renderNodes(node.children) — fields inside keep working.

A field ({ field: true }) must forwardRef to an input that holds its value and call onChange when it changes; then required, values, onChange actions and onSubmit work like built-in fields.

Register once, at the top of a file that runs before the form (e.g. a components.js you import in the page). The Components tab has the code.

Try it

Loading example…
Events0
Use the example — every action it runs shows up here with its data.

Code

Copy Full page.js into app/your-page/page.js of a Next.js app (withrcube-html, react-bootstrap and Bootstrap's CSS installed) — it runs as is. Or copy only the schema and keep your own page.

[
  {
    "type": "row",
    "id": "row-stats",
    "props": {
      "className": "g-3"
    },
    "children": [
      {
        "type": "column",
        "id": "c-s1",
        "props": {
          "className": "col-6 col-md-4"
        },
        "children": [
          {
            "type": "Stat",
            "id": "stat-users",
            "props": {
              "label": "Users",
              "value": "1,284",
              "trend": "+12%"
            }
          }
        ]
      },
      {
        "type": "column",
        "id": "c-s2",
        "props": {
          "className": "col-6 col-md-4"
        },
        "children": [
          {
            "type": "Stat",
            "id": "stat-orders",
            "props": {
              "label": "Orders",
              "value": "342",
              "trend": "-3%"
            }
          }
        ]
      },
      {
        "type": "column",
        "id": "c-s3",
        "props": {
          "className": "col-12 col-md-4"
        },
        "children": [
          {
            "type": "Stat",
            "id": "stat-revenue",
            "props": {
              "label": "Revenue",
              "value": "$18.2K",
              "trend": "+8%"
            }
          }
        ]
      }
    ]
  },
  {
    "type": "row",
    "id": "row-panel",
    "children": [
      {
        "type": "column",
        "id": "c-panel",
        "children": [
          {
            "type": "Panel",
            "id": "feedback",
            "props": {
              "title": "Feedback (a custom container)"
            },
            "children": [
              {
                "type": "RatingField",
                "id": "rating",
                "props": {
                  "name": "rating",
                  "label": "How did we do?",
                  "required": true,
                  "onChange": "ratingChanged()"
                }
              },
              {
                "type": "TextareaField",
                "id": "comment",
                "props": {
                  "name": "comment",
                  "label": "Comment",
                  "rows": 2
                }
              }
            ]
          },
          {
            "type": "ButtonField",
            "id": "send",
            "props": {
              "type": "submit",
              "text": "Send",
              "onClick": "runValidation()"
            }
          },
          {
            "type": "ButtonField",
            "id": "bump",
            "props": {
              "text": "Update a Stat from code",
              "variant": "outline-secondary",
              "className": "ms-2",
              "onClick": "bumpUsers()"
            }
          }
        ]
      }
    ]
  }
]

Options used here

OptionWhat it does
registerComponent(name, Component)Use Component as { type: name }.
{ container: true }Receives node, nodeId, items, renderNodes, actions.
{ field: true }forwardRef to the value input; receives name, label, error, onChange, required, ...

Events

EventWhen it runsYour action receives
onChange (custom field)Your field calls onChange.(event, { name, value })
onSubmitValid submit — the rating is required.[{ rating: "4", comment: "..." }]