← Back to all how-tos

Create a brick

Validate values

Add validation to sidebar controls so editors get feedback when they enter invalid values.

Estimated time: 3 minRaw Markdown

What you'll build

In this how-to, you'll add a validation rule to the LinkButton brick from the previous guide.

We'll validate the path sidebar field so it only accepts:

  • internal paths starting with /
  • full URLs starting with https://

If the value is not valid, React Bricks can show an error message to the editor.

Start from the LinkButton brick

Suppose you already have a LinkButton brick like this:

import { types, Link, Text } from 'react-bricks/rsc'
import clsx from 'clsx'
 
interface LinkButtonProps {
  buttonText: types.TextValue
  path: string
  type?: 'primary' | 'secondary'
}
 
const LinkButton: types.Brick<LinkButtonProps> = ({
  buttonText,
  path,
  type = 'primary',
}) => (
  <Link
    href={path}
    className={clsx(
      'inline-block text-center font-semibold leading-6 transition-colors rounded-full px-8 py-3 border',
      type === 'primary'
        ? 'text-white bg-indigo-500 hover:bg-indigo-500/90 border-indigo-500'
        : 'text-indigo-500 bg-indigo-50 hover:bg-indigo-50/50 border-indigo-50 hover:border-indigo-200'
    )}
  >
    <Text
      propName="buttonText"
      value={buttonText}
      placeholder="Type an action..."
      renderBlock={({ children }) => <span>{children}</span>}
    />
  </Link>
)
 
LinkButton.schema = {
  name: 'ws-button',
  label: 'Link Button',
  getDefaultProps: () => ({
    buttonText: 'Click me',
    type: 'primary',
    path: '/',
  }),
  sideEditProps: [
    {
      name: 'path',
      label: 'Path',
      type: types.SideEditPropType.Text,
    },
    {
      name: 'type',
      label: 'Type',
      type: types.SideEditPropType.Select,
      selectOptions: {
        display: types.OptionsDisplay.Radio,
        options: [
          { value: 'primary', label: 'Primary' },
          { value: 'secondary', label: 'Secondary' },
        ],
      },
    },
  ],
}
 
export default LinkButton

Now we'll add validation for the path field.

Add validate to the sidebar prop

Update the path sidebar control like this:

{
  name: 'path',
  label: 'Path',
  type: types.SideEditPropType.Text,
  validate: (value) =>
    value.startsWith('/') || value.startsWith('https://') || 'Invalid Path',
},

How validate works

The validate function accepts 2 arguments:

  • the current value of this sidebar control
  • an object containing all the brick props

That means you can validate a single field by itself, or also create cross-field validation rules that depend on other prop values.

The function must return one of these:

  • true: validation passes
  • false: validation fails
  • a string: validation fails and that string is shown as the error message

So in this example:

  • /about passes
  • https://reactbricks.com passes
  • contact fails with the message Invalid Path

Using a string is often the best option, because it gives editors a clear explanation of what is wrong.

For example, the function signature can be written like this:

validate: (value, allProps) => {
  // value: current field value
  // allProps: all brick props
  return true
}

Why this validation is useful

Without validation, an editor could type something like:

about-us

and think it is a valid path.

With validation in place, React Bricks can immediately show that the value is not valid, helping editors fix the problem before publishing.

Final code

Your full LinkButton.tsx file should now look like this:

import { types, Link, Text } from 'react-bricks/rsc'
import clsx from 'clsx'
 
interface LinkButtonProps {
  buttonText: types.TextValue
  path: string
  type?: 'primary' | 'secondary'
}
 
const LinkButton: types.Brick<LinkButtonProps> = ({
  buttonText,
  path,
  type = 'primary',
}) => (
  <Link
    href={path}
    className={clsx(
      'inline-block text-center font-semibold leading-6 transition-colors rounded-full px-8 py-3 border',
      type === 'primary'
        ? 'text-white bg-indigo-500 hover:bg-indigo-500/90 border-indigo-500'
        : 'text-indigo-500 bg-indigo-50 hover:bg-indigo-50/50 border-indigo-50 hover:border-indigo-200'
    )}
  >
    <Text
      propName="buttonText"
      value={buttonText}
      placeholder="Type an action..."
      renderBlock={({ children }) => <span>{children}</span>}
    />
  </Link>
)
 
LinkButton.schema = {
  name: 'ws-button',
  label: 'Link Button',
  getDefaultProps: () => ({
    buttonText: 'Click me',
    type: 'primary',
    path: '/',
  }),
  sideEditProps: [
    {
      name: 'path',
      label: 'Path',
      type: types.SideEditPropType.Text,
      validate: (value) =>
        value.startsWith('/') || value.startsWith('https://') || 'Invalid Path',
    },
    {
      name: 'type',
      label: 'Type',
      type: types.SideEditPropType.Select,
      selectOptions: {
        display: types.OptionsDisplay.Radio,
        options: [
          { value: 'primary', label: 'Primary' },
          { value: 'secondary', label: 'Secondary' },
        ],
      },
    },
  ],
}
 
export default LinkButton

Validation and saving

In the React Bricks configuration, you can decide how validation errors affect saving.

Depending on your configuration, you can:

  • allow editors to save a page even if there are validation errors
  • prevent saving if there is at least one validation error on a brick

This gives you flexibility: during content editing you may prefer softer warnings, while in stricter setups you may want to block invalid content completely.

What's next

Your brick now validates user input before it gets saved.

From here, you can add more advanced validation rules for numbers, ranges, formats, or relationships between multiple props.