# How to Implement Custom Editor Panels for Plugin Properties in Luban H5

> Learn to implement custom editor panels for plugin properties in Luban H5. Replace the default form with a specialized interface using lazy-loaded Vue components.

- Repository: [小小鲁班/luban-h5](https://github.com/ly525/luban-h5)
- Tags: how-to-guide
- Published: 2026-03-06

---

**Set `custom: true` in your plugin definition and provide a lazy-loaded Vue component via the `editor` field to replace the generic right-panel form with a specialized property interface.**

Luban H5 is an open-source visual page builder that relies on a plugin-based architecture for its components. While the default right-panel UI handles standard property editing, complex plugins often require specialized interfaces for rich configuration. This guide explains how to implement custom editor panels for plugin properties in Luban H5 by leveraging the `custom` flag, lazy-loaded editor components, and the core rendering logic in [`props.js`](https://github.com/ly525/luban-h5/blob/main/props.js).

## How Luban H5 Discovers Custom Editors

The editor follows a four-step resolution process to determine whether to render a generic form or a custom Vue component.

### Plugin Registration with the `custom` Flag

In the plugin's main entry file, setting `custom: true` signals to the core that this component provides its own property editor. The `editor` property points to a Vue component that the core loads lazily.

In [`front-end/h5/src/components/core/plugins/lbp-slide.js`](https://github.com/ly525/luban-h5/blob/main/front-end/h5/src/components/core/plugins/lbp-slide.js), you can see this pattern in production plugins.

### Right-Panel Rendering Logic

The file [`front-end/h5/src/components/core/editor/right-panel/props.js`](https://github.com/ly525/luban-h5/blob/main/front-end/h5/src/components/core/editor/right-panel/props.js) contains the logic that reads the plugin's prop schema. When it encounters `custom: true` at the plugin level, it imports and renders the component specified in the `editor` field instead of the default form generator.

### Prop-Level Customization

Individual properties within the schema can also declare `custom: true`. This allows fine-grained control where specific fields use dedicated sub-editors (such as color pickers or table editors) while other fields remain generic.

## Required Files and Project Structure

To implement a custom editor panel, you will create or modify the following files:

| File Path | Purpose | Required Changes |
|-----------|---------|------------------|
| `front-end/h5/src/components/core/plugins/<your-plugin>.js` | Plugin registration and schema definition | Add `custom: true` and `editor: () => import('./editor.vue')` |
| `front-end/h5/src/components/core/plugins/<your-plugin>/editor.vue` | Custom property panel UI | Implement the Vue component using Luban UI primitives like `LbFormItem` and `LbInput` |
| [`front-end/h5/src/components/core/editor/right-panel/props.js`](https://github.com/ly525/luban-h5/blob/main/front-end/h5/src/components/core/editor/right-panel/props.js) | Core rendering logic | No changes required unless extending the loader |

## Step-by-Step Implementation

### Step 1: Create the Plugin Entry

Define your plugin with the `custom` flag and lazy-loaded editor path.

```javascript
// front-end/h5/src/components/core/plugins/my-plugin.js
import MyComponent from './MyComponent.vue'

export default {
  name: 'my-plugin',
  component: MyComponent,

  // ★ Tell Luban to use a custom property editor
  custom: true,

  // Path to the editor UI (lazy‑loaded)
  editor: () => import('./editor.vue'),

  // Example of a prop that also uses a custom sub‑editor
  props: {
    items: {
      type: Array,
      default: () => [],
      // Each item will be edited by a dedicated sub‑editor
      custom: true
    }
  }
}

```

### Step 2: Build the Custom Editor Component

Create the Vue component that renders in the right panel. Use Luban's UI primitives and Vuex helpers to bind data.

```vue
<template>
  <div class="my-plugin-editor">
    <lb-form-item :label="$t('items')">
      <lb-button type="primary" @click="addItem">
        {{ $t('addItem') }}
      </lb-button>
    </lb-form-item>

    <div v-for="(item, i) in value.items" :key="i" class="item-row">
      <lb-input v-model="item.text" :placeholder="$t('itemText')" />
      <lb-button @click="removeItem(i)">{{ $t('remove') }}</lb-button>
    </div>
  </div>
</template>

<script>
import { mapState, mapMutations } from 'vuex'
export default {
  name: 'MyPluginEditor',
  computed: {
    // `editingElement` is the element currently selected in the canvas
    ...mapState('editor', ['editingElement']),
    // Shortcut to plugin‑specific data
    value() {
      return this.editingElement
    }
  },
  methods: {
    ...mapMutations('editor', ['updateEditingElement']),
    addItem() {
      const items = [...this.value.items, { text: '' }]
      this.updateEditingElement({ items })
    },
    removeItem(idx) {
      const items = this.value.items.filter((_, i) => i !== idx)
      this.updateEditingElement({ items })
    }
  }
}
</script>

<style scoped>
.item-row {
  display: flex;
  align-items: center;
  margin-top: 8px;
}
</style>

```

## Key Source Files Reference

Understanding the core implementation helps debug custom editors. These files handle the detection and rendering logic:

- **[`front-end/h5/src/components/core/editor/right-panel/props.js`](https://github.com/ly525/luban-h5/blob/main/front-end/h5/src/components/core/editor/right-panel/props.js)** – Core logic that inspects the plugin schema and renders either the generic form or the custom `editor` component.
- **[`front-end/h5/src/components/core/plugins/lbp-slide.js`](https://github.com/ly525/luban-h5/blob/main/front-end/h5/src/components/core/plugins/lbp-slide.js)** – Production example demonstrating the `custom: true` flag.
- **[`docs/zh/plugin-development/how-it-works/custom-editor-single-prop.md`](https://github.com/ly525/luban-h5/blob/main/docs/zh/plugin-development/how-it-works/custom-editor-single-prop.md)** – Documentation for single-property custom editors.
- **[`docs/zh/plugin-development/how-it-works/custom-editor-multiple-props.md`](https://github.com/ly525/luban-h5/blob/main/docs/zh/plugin-development/how-it-works/custom-editor-multiple-props.md)** – Documentation for multi-property custom editors.

## Best Practices and Performance Tips

When building custom editor panels for Luban H5 plugins, follow these guidelines to ensure maintainability and performance:

- **Use lazy loading** – Always define the `editor` property as a function returning a dynamic import: `editor: () => import('./editor.vue')`. The core system invokes this function only when the user selects your plugin, keeping the initial application bundle small.
- **Bind to Vuex correctly** – Access the selected element via `mapState('editor', ['editingElement'])` and commit changes through `mapMutations('editor', ['updateEditingElement'])`. This ensures that modifications in your custom right-panel are immediately reflected on the canvas and persisted with the project data.
- **Scope your styles** – Always add `scoped` to the `<style>` tag in [`editor.vue`](https://github.com/ly525/luban-h5/blob/main/editor.vue) to prevent CSS leaks into the canvas or other editor panels.
- **Leverage Luban UI primitives** – Use `LbFormItem`, `LbInput`, `LbButton`, and `LbSelect` instead of raw HTML elements to maintain visual consistency with the rest of the builder.
- **Internationalize labels** – Use `$t('key')` for all user-facing strings, adding keys to `src/locales/lang/*.js` to support multiple languages.

## Summary

To implement custom editor panels for plugin properties in Luban H5:

- Set **`custom: true`** in your plugin definition to signal the core to bypass the generic form.
- Provide an **`editor`** function that lazy-loads your Vue component (e.g., `editor: () => import('./editor.vue')`).
- Build the editor component using Luban UI primitives and Vuex helpers (`mapState`, `mapMutations`) to bind to the selected canvas element.
- Optionally mark individual **`props`** with `custom: true` for fine-grained control over specific fields.

The core logic in [`front-end/h5/src/components/core/editor/right-panel/props.js`](https://github.com/ly525/luban-h5/blob/main/front-end/h5/src/components/core/editor/right-panel/props.js) handles the rest, automatically swapping the default panel for your custom implementation whenever users select your plugin on the canvas.

## Frequently Asked Questions

### How does Luban H5 decide when to show a custom editor versus the default property form?

The right-panel controller in [`front-end/h5/src/components/core/editor/right-panel/props.js`](https://github.com/ly525/luban-h5/blob/main/front-end/h5/src/components/core/editor/right-panel/props.js) inspects the selected plugin's schema. If the plugin object contains `custom: true`, the core imports the component specified in the `editor` field and renders it instead of iterating through the generic prop schema. If `custom` is falsy or omitted, the system falls back to the standard form generator.

### Can I use a custom editor for just one specific property while keeping the rest generic?

Yes. You can mark individual properties with `custom: true` inside the `props` definition. When the generic form generator encounters a prop with this flag, it looks for a dedicated editor component for that specific field while rendering standard inputs for all other properties. This hybrid approach allows you to build specialized interfaces for complex fields without reimplementing the entire panel.

### What is the recommended way to handle state synchronization between the custom editor and the canvas?

Always use the Vuex store module `editor` provided by Luban H5. Access the currently selected element via `mapState('editor', ['editingElement'])` and commit changes using `mapMutations('editor', ['updateEditingElement'])`. This ensures that modifications in your custom right-panel are immediately reflected on the canvas and persisted with the project data. Directly mutating the element object without the mutation may cause reactivity issues or break undo/redo functionality.

### Does implementing a custom editor affect the initial bundle size of the Luban H5 builder?

No, provided you use lazy loading. Define the `editor` property as a function returning a dynamic import: `editor: () => import('./editor.vue')`. The core system invokes this function only when the user selects your plugin, causing the custom editor code to be fetched on demand. This keeps the initial application bundle small and improves startup performance for the page builder.```markdown

# How to Implement Custom Editor Panels for Plugin Properties in Luban H5

**Set `custom: true` in your plugin definition and provide a Vue component via the `editor` field to replace the generic right-panel form with a specialized property interface.**

Luban H5 is an open-source visual page builder that relies on a plugin-based architecture for its components. While the default right-panel UI handles basic property editing, complex plugins often require specialized interfaces for rich configuration. This guide explains how to implement custom editor panels for plugin properties in Luban H5 by leveraging the `custom` flag, lazy-loaded editor components, and the core rendering logic in `props.js`.

## How Luban H5 Discovers Custom Editors

The editor follows a four-step resolution process to determine whether to render a generic form or a custom Vue component.

### Plugin Registration with the `custom` Flag

In the plugin's main entry file, setting `custom: true` signals to the core that this component provides its own property editor. The `editor` property points to a Vue component that the core loads lazily.

In `front-end/h5/src/components/core/plugins/lbp-slide.js`, you can see this pattern in production plugins.

### Right-Panel Rendering Logic

The file `front-end/h5/src/components/core/editor/right-panel/props.js` contains the logic that reads the plugin's prop schema. When it encounters `custom: true` at the plugin level, it imports and renders the component specified in the `editor` field instead of the default form generator.

### Prop-Level Customization

Individual properties within the schema can also declare `custom: true`. This allows fine-grained control where specific fields use dedicated sub-editors (such as color pickers or table editors) while other fields remain generic.

## Required Files and Project Structure

To implement a custom editor panel, you will create or modify the following files:

| File Path | Purpose | Required Changes |
|-----------|---------|------------------|
| `front-end/h5/src/components/core/plugins/<your-plugin>.js` | Plugin registration and schema definition | Add `custom: true` and `editor: () => import('./editor.vue')` |
| `front-end/h5/src/components/core/plugins/<your-plugin>/editor.vue` | Custom property panel UI | Implement the Vue component using Luban UI primitives like `LbFormItem` and `LbInput` |
| `front-end/h5/src/components/core/editor/right-panel/props.js` | Core rendering logic | No changes required unless extending the loader |

## Step-by-Step Implementation

### Step 1: Create the Plugin Entry

Define your plugin with the `custom` flag and lazy-loaded editor path.

```javascript
// front-end/h5/src/components/core/plugins/my-plugin.js
import MyComponent from './MyComponent.vue'

export default {
  name: 'my-plugin',
  component: MyComponent,

  // ★ Tell Luban to use a custom property editor
  custom: true,

  // Path to the editor UI (lazy‑loaded)
  editor: () => import('./editor.vue'),

  // Example of a prop that also uses a custom sub‑editor
  props: {
    items: {
      type: Array,
      default: () => [],
      // Each item will be edited by a dedicated sub‑editor
      custom: true
    }
  }
}

```

### Step 2: Build the Custom Editor Component

Create the Vue component that renders in the right panel. Use Luban's UI primitives and Vuex helpers to bind data.

```vue
<template>
  <div class="my-plugin-editor">
    <lb-form-item :label="$t('items')">
      <lb-button type="primary" @click="addItem">
        {{ $t('addItem') }}
      </lb-button>
    </lb-form-item>

    <div v-for="(item, i) in value.items" :key="i" class="item-row">
      <lb-input v-model="item.text" :placeholder="$t('itemText')" />
      <lb-button @click="removeItem(i)">{{ $t('remove') }}</lb-button>
    </div>
  </div>
</template>

<script>
import { mapState, mapMutations } from 'vuex'
export default {
  name: 'MyPluginEditor',
  computed: {
    // `editingElement` is the element currently selected in the canvas
    ...mapState('editor', ['editingElement']),
    // Shortcut to plugin‑specific data
    value() {
      return this.editingElement
    }
  },
  methods: {
    ...mapMutations('editor', ['updateEditingElement']),
    addItem() {
      const items = [...this.value.items, { text: '' }]
      this.updateEditingElement({ items })
    },
    removeItem(idx) {
      const items = this.value.items.filter((_, i) => i !== idx)
      this.updateEditingElement({ items })
    }
  }
}
</script>

<style scoped>
.item-row {
  display: flex;
  align-items: center;
  margin-top: 8px;
}
</style>

```

## Key Source Files Reference

Understanding the core implementation helps debug custom editors. These files handle the detection and rendering logic:

- **`front-end/h5/src/components/core/editor/right-panel/props.js`** – Core logic that inspects the plugin schema and renders either the generic form or the custom `editor` component.
- **`front-end/h5/src/components/core/plugins/lbp-slide.js`** – Production example demonstrating the `custom: true` flag.
- **`docs/zh/plugin-development/how-it-works/custom-editor-single-prop.md`** – Documentation for single-property custom editors.
- **`docs/zh/plugin-development/how-it-works/custom-editor-multiple-props.md`** – Documentation for multi-property custom editors.

## Best Practices and Performance Tips

When building custom editor panels for Luban H5 plugins, follow these guidelines to ensure maintainability and performance:

- **Use lazy loading** – Always define the `editor` property as a function returning a dynamic import: `editor: () => import('./editor.vue')`. This prevents the custom editor code from bloating the initial bundle.
- **Bind to Vuex correctly** – Access the selected element via `mapState('editor', ['editingElement'])` and commit changes using `mapMutations('editor', ['updateEditingElement'])`. This ensures that modifications in your custom right-panel are immediately reflected on the canvas and persisted with the project data.
- **Scope your styles** – Always add `scoped` to the `<style>` tag in `editor.vue` to prevent CSS leaks into the canvas.
- **Leverage Luban UI primitives** – Use `LbFormItem`, `LbInput`, `LbButton`, and `LbSelect` instead of raw HTML elements to maintain visual consistency with the rest of the builder.
- **Internationalize labels** – Use `$t('key')` for all user-facing strings, adding keys to `src/locales/lang/*.js` to support multiple languages.

## Summary

To implement custom editor panels for plugin properties in Luban H5:

- Set **`custom: true`** in your plugin definition to signal the core to bypass the generic form.
- Provide an **`editor`** function that lazy-loads your Vue component (e.g., `editor: () => import('./editor.vue')`).
- Build the editor component using Luban UI primitives and Vuex helpers (`mapState`, `mapMutations`) to bind to the selected canvas element.
- Optionally mark individual **`props`** with `custom: true` for fine-grained control over specific fields.

The core logic in `front-end/h5/src/components/core/editor/right-panel/props.js` handles the rest, automatically swapping the default panel for your custom implementation whenever users select your plugin on the canvas.

## Frequently Asked Questions

### How does Luban H5 decide when to show a custom editor versus the default property form?

The right-panel controller in `front-end/h5/src/components/core/editor/right-panel/props.js` inspects the selected plugin's schema. If the plugin object contains `custom: true`, the core imports the component specified in the `editor` field and renders it instead of iterating through the generic prop schema. If `custom` is falsy or omitted, the system falls back to the standard form generator.

### Can I use a custom editor for just one specific property while keeping the rest generic?

Yes. You can mark individual properties with `custom: true` inside the `props` definition. When the generic form generator encounters a prop with this flag, it looks for a dedicated editor component for that specific field while rendering standard inputs for all other properties. This hybrid approach allows you to build specialized interfaces for complex fields without reimplementing the entire panel.

### What is the recommended way to handle state synchronization between the custom editor and the canvas?

Always use the Vuex store module `editor` provided by Luban H5. Access the currently selected element via `mapState('editor', ['editingElement'])` and commit changes using `mapMutations('editor', ['updateEditingElement'])`. This ensures that modifications in your custom right-panel are immediately reflected on the canvas and persisted with the project data. Directly mutating the element object without the mutation may cause reactivity issues or break undo/redo functionality.

### Does implementing a custom editor affect the initial bundle size of the Luban H5 builder?

No, provided you use lazy loading. Define the `editor` property as a function returning a dynamic import: `editor: () => import('./editor.vue')`. The core system invokes this function only when the user selects your plugin, causing the custom editor code to be fetched on demand. This keeps the initial application bundle small and improves startup performance for the page builder.```