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

Filters the whole list of rendered controls for one placement, group and nesting level. Reach for it to group controls into sections of your own, or to rebuild the list from the raw control data instead of patching elements you cannot inspect.

Note the plural. [lzb.editor.control.render](https://www.lazyblocks.com/docs/js-filters/lzb-editor-control-render/) filters a single control, takes three arguments, and runs only after the type-specific `lzb.editor.control.CONTROL_TYPE.render` filter returned something truthy. This one filters the finished list, takes two arguments, and always runs, including when nothing rendered.

## Attributes

| Name     | Type             | Description                                                                         |
| -------- | ---------------- | ----------------------------------------------------------------------------------- |
| `result` | **Array \| JSX** | rendered controls, or one `PanelBody` wrapping them when the placement is inspector |
| `data`   | **Object**       | `placement`, `group`, `childOf`, `childIndex`, `getControls`, `renderControl`       |

| Name            | Type                  | Description                                                                     |
| --------------- | --------------------- | ------------------------------------------------------------------------------- |
| `placement`     | **String**            | `inspector` or `content`                                                        |
| `group`         | **String**            | `default`, `content`, `list`, `styles` or `advanced`                            |
| `childOf`       | **String**            | uid of the parent control, `''` at the top level                                |
| `childIndex`    | **Number \| Boolean** | repeater row index, `false` outside a repeater                                  |
| `getControls`   | **Function**          | `getControls(childOf)` returns the raw controls of that level, keyed by uid     |
| `renderControl` | **Function**          | `renderControl(control, placement, uid, childIndex, group)` renders one control |

A control stored with the group `settings` is normalised to `default` before the filter runs, so match on `default` and never on `settings`. Content placement and repeater rows are both rendered without a group argument, so they always arrive as `group: 'default'`.

When `placement` is `inspector` and at least one control rendered, `result` is a single `PanelBody` element rather than the array. Check for that before treating the value as a list.

## Usage

The Pro Panel control throws the default result away and rebuilds the list, which is what `getControls` and `renderControl` are there for.

```js title="JS"
const { PanelBody } = wp.components;

wp.hooks.addFilter(
  "lzb.editor.controls.render",
  "my.custom.namespace",
  function (result, data) {
    const {
      placement,
      group,
      childOf,
      childIndex,
      getControls,
      renderControl,
    } = data;

    if (placement !== "inspector") {
      return result;
    }

    const controls = getControls(childOf);
    const main = [];
    const advanced = [];

    Object.keys(controls).forEach((uid) => {
      const rendered = renderControl(
        controls[uid],
        placement,
        uid,
        childIndex,
        group,
      );

      if (!rendered) {
        return;
      }

      if (controls[uid].name.indexOf("advanced_") === 0) {
        advanced.push(rendered);
      } else {
        main.push(rendered);
      }
    });

    if (!advanced.length) {
      return result;
    }

    return [
      <PanelBody key="main">{main}</PanelBody>,
      <PanelBody key="advanced" title="Advanced" initialOpen={false}>
        {advanced}
      </PanelBody>,
    ];
  },
);
```

`renderControl` returns `false` for a control whose placement or group does not match the arguments you passed, so drop the falsy results rather than pushing them into the list. Whatever you return is rendered as it stands, which means an array without a `key` on each element makes React warn on every editor render.

## 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
