Skip to content
JS Filters

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

NameTypeDescription
renderJSXthe element the control type returned
controlDataObjectdata, placement, childIndex, uniqueId, getValue, onChange, getControls, renderControls
propsObjectprops of the block being edited, with the block record under lazyBlockData
NameTypeDescription
dataObjectthe control's settings, with label and help already wrapped in elements
placementStringcontent or inspector
childIndexNumber | Booleanrow index inside a repeater, false outside one
uniqueIdStringkey of this control inside props.lazyBlockData.controls
getValueFunctionreads the current value, through lzb.editor.control.getValue
onChangeFunctionwrites a new value, through lzb.editor.control.updateValue
getControlsFunctionreturns the block's controls, or the children of one when given a parent name
renderControlsFunctionrenders a whole placement and group, used by repeater controls for their rows

Additional Filters

NameDescription
lzb.editor.control.CONTROL_TYPE.renderspecific 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
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
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, which filters the finished list for one placement and group.

Was this article helpful?

Copyright © 2026 Lazy Blocks.