---
title: "lzb.editor.control.render"
description: "JS filter `lzb.editor.control.render` of the Lazy Blocks WordPress plugin."
url: "https://www.lazyblocks.com/docs/js-filters/lzb-editor-control-render/"
lastUpdated: 2026-09-09
source: "js-filters/lzb-editor-control-render.mdx"
---
# lzb.editor.control.render

Filters the element one control renders in the block editor, after the control type has produced it. Use it to wrap a control in markup of your own, or use the type-specific name to give a control type its editor UI in the first place.

## Attributes

| Name          | Type       | Description                                                                                            |
| ------------- | ---------- | ------------------------------------------------------------------------------------------------------ |
| `render`      | **JSX**    | the element the control type returned                                                                  |
| `controlData` | **Object** | `data`, `placement`, `childIndex`, `uniqueId`, `getValue`, `onChange`, `getControls`, `renderControls` |
| `props`       | **Object** | props of the block being edited, with the block record under `lazyBlockData`                           |

| Name             | Type                  | Description                                                                                                    |
| ---------------- | --------------------- | -------------------------------------------------------------------------------------------------------------- |
| `data`           | **Object**            | the control's settings, with `label` and `help` already wrapped in elements                                    |
| `placement`      | **String**            | `content` or `inspector`                                                                                       |
| `childIndex`     | **Number \| Boolean** | row index inside a repeater, `false` outside one                                                               |
| `uniqueId`       | **String**            | key of this control inside `props.lazyBlockData.controls`                                                      |
| `getValue`       | **Function**          | reads the current value, through [lzb.editor.control.getValue](https://www.lazyblocks.com/docs/js-filters/lzb-editor-control-getvalue/)  |
| `onChange`       | **Function**          | writes a new value, through [lzb.editor.control.updateValue](https://www.lazyblocks.com/docs/js-filters/lzb-editor-control-updatevalue/) |
| `getControls`    | **Function**          | returns the block's controls, or the children of one when given a parent name                                  |
| `renderControls` | **Function**          | renders a whole placement and group, used by repeater controls for their rows                                  |

## Additional Filters

| Name                                     | Description            |
| ---------------------------------------- | ---------------------- |
| `lzb.editor.control.CONTROL_TYPE.render` | specific controls only |

The type-specific filter runs first, and this one only runs when that filter returned something. A control type with no registered renderer never reaches it.

## Usage

The type-specific name starts from an empty string, which makes it the place to register the UI of a control type of your own:

```js title="JS"
wp.hooks.addFilter(
  "lzb.editor.control.my_rating.render",
  "my.custom.namespace",
  function (render, controlData) {
    const { RangeControl } = wp.components;

    return (
      <RangeControl
        label={controlData.data.label}
        help={controlData.data.help}
        min={0}
        max={5}
        value={Number(controlData.getValue()) || 0}
        onChange={(value) => controlData.onChange(String(value))}
      />
    );
  },
);
```

The generic name receives whatever that produced, for every control on every block:

```js title="JS"
wp.hooks.addFilter(
  "lzb.editor.control.render",
  "my.custom.namespace",
  function (render, controlData) {
    if (controlData.data.type !== "textarea") {
      return render;
    }

    const length = String(controlData.getValue() || "").length;

    return (
      <>
        {render}
        <p className="description">{length} characters</p>
      </>
    );
  },
);
```

Both filters run on every render of the block, so a handler that reads the value with `getValue` should stay cheap. Returning a falsy value from either filter drops the control from the editor entirely, and a falsy return from the type-specific one also stops the generic filter from running for that control. To reorder or wrap the whole group of controls at once rather than each one, use [lzb.editor.controls.render](https://www.lazyblocks.com/docs/js-filters/lzb-editor-controls-render/), which filters the finished list for one placement and group.

## Documentation Index
> Fetch the complete documentation index at: https://www.lazyblocks.com/llms.txt
> Fetch every page in a single file at: https://www.lazyblocks.com/llms-full.txt
