umbraco-manifest-picker
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseUmbraco Manifest Picker
Umbraco Manifest选择器
What is it?
是什么?
The component provides a picker UI for selecting registered extensions from the Umbraco extension registry. It allows users to pick from any extension type (workspaces, dashboards, property editors, etc.) and returns the selected manifest. This is useful for configuration UIs where users need to reference other extensions.
<umb-input-manifest><umb-input-manifest>Documentation
文档
Always fetch the latest docs before implementing:
Reference Example
参考示例
The Umbraco source includes a working example:
Location:
/Umbraco-CMS/src/Umbraco.Web.UI.Client/examples/manifest-picker/This example demonstrates a dashboard that lets users browse and select extensions by type.
Umbraco源码中包含一个可用示例:
位置:/Umbraco-CMS/src/Umbraco.Web.UI.Client/examples/manifest-picker/
该示例展示了一个允许用户按类型浏览和选择扩展的仪表板。
Related Foundation Skills
相关基础技能
-
Extension Registry: For understanding how extensions are registered
- Reference skill:
umbraco-extension-registry
- Reference skill:
-
Umbraco Element: For creating picker UIs
- Reference skill:
umbraco-umbraco-element
- Reference skill:
-
扩展注册表:用于理解扩展的注册方式
- 参考技能:
umbraco-extension-registry
- 参考技能:
-
Umbraco元素:用于创建选择器UI
- 参考技能:
umbraco-umbraco-element
- 参考技能:
Workflow
工作流程
- Fetch docs - Use WebFetch on the URLs above
- Ask questions - What extension types to pick? How to use selection?
- Generate files - Create element with manifest picker
- Explain - Show what was created and how selection works
- 获取文档 - 使用WebFetch访问上述URL
- 提出问题 - 要选择哪些扩展类型?如何使用选择结果?
- 生成文件 - 创建包含manifest选择器的元素
- 说明 - 展示创建的内容以及选择功能的工作方式
Basic Usage
基本用法
typescript
import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import type { UmbInputManifestElement } from '@umbraco-cms/backoffice/components';
@customElement('my-manifest-picker-example')
export class MyManifestPickerExampleElement extends UmbLitElement {
@state()
private _selectedManifest = '';
#onChange(event: { target: UmbInputManifestElement }) {
const selectedManifest = event.target.value;
this._selectedManifest = selectedManifest?.value ?? '';
}
override render() {
return html`
<uui-box>
<umb-property-layout label="Select a workspace">
<div slot="editor">
<umb-input-manifest
.extensionType=${'workspace'}
@change=${this.#onChange}
></umb-input-manifest>
</div>
</umb-property-layout>
${this._selectedManifest
? html`<p>Selected: <code>${this._selectedManifest}</code></p>`
: ''}
</uui-box>
`;
}
}typescript
import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import type { UmbInputManifestElement } from '@umbraco-cms/backoffice/components';
@customElement('my-manifest-picker-example')
export class MyManifestPickerExampleElement extends UmbLitElement {
@state()
private _selectedManifest = '';
#onChange(event: { target: UmbInputManifestElement }) {
const selectedManifest = event.target.value;
this._selectedManifest = selectedManifest?.value ?? '';
}
override render() {
return html`
<uui-box>
<umb-property-layout label="Select a workspace">
<div slot="editor">
<umb-input-manifest
.extensionType=${'workspace'}
@change=${this.#onChange}
></umb-input-manifest>
</div>
</umb-property-layout>
${this._selectedManifest
? html`<p>Selected: <code>${this._selectedManifest}</code></p>`
: ''}
</uui-box>
`;
}
}Dynamic Extension Type Selection
动态扩展类型选择
typescript
import { html, customElement, state, when, nothing } from '@umbraco-cms/backoffice/external/lit';
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import type { UmbInputManifestElement } from '@umbraco-cms/backoffice/components';
import type { UUISelectEvent } from '@umbraco-cms/backoffice/external/uui';
interface Option {
name: string;
value: string;
selected: boolean;
}
@customElement('my-extension-browser')
export class MyExtensionBrowserElement extends UmbLitElement {
#options: Option[] = [];
@state()
private _selectedExtensionType = 'dashboard';
@state()
private _selectedManifest = '';
constructor() {
super();
// Build list of available extension types from registry
this.observe(umbExtensionsRegistry.extensions, (extensions) => {
const types = [...new Set(extensions.map((x) => x.type))];
this.#options = types.sort().map((x) => ({
name: x,
value: x,
selected: x === this._selectedExtensionType,
}));
});
}
#onTypeSelect(event: UUISelectEvent) {
this._selectedManifest = '';
this._selectedExtensionType = event.target.value as string;
}
#onManifestChange(event: { target: UmbInputManifestElement }) {
const selectedManifest = event.target.value;
this._selectedManifest = selectedManifest?.value ?? '';
}
override render() {
return html`
<uui-box>
<umb-property-layout label="Extension Type">
<uui-select
slot="editor"
label="Select type"
placeholder="Select type..."
.options=${this.#options}
@change=${this.#onTypeSelect}
></uui-select>
</umb-property-layout>
${when(
this._selectedExtensionType,
() => html`
<umb-property-layout
label="Select Extension"
description="Pick a ${this._selectedExtensionType}"
>
<div slot="editor">
<umb-input-manifest
.extensionType=${this._selectedExtensionType}
@change=${this.#onManifestChange}
></umb-input-manifest>
</div>
</umb-property-layout>
`,
() => nothing
)}
${when(
this._selectedManifest,
() => html`
<umb-property-layout label="Selected Manifest">
<div slot="editor">
<code>${this._selectedManifest}</code>
</div>
</umb-property-layout>
`,
() => nothing
)}
</uui-box>
`;
}
}typescript
import { html, customElement, state, when, nothing } from '@umbraco-cms/backoffice/external/lit';
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import type { UmbInputManifestElement } from '@umbraco-cms/backoffice/components';
import type { UUISelectEvent } from '@umbraco-cms/backoffice/external/uui';
interface Option {
name: string;
value: string;
selected: boolean;
}
@customElement('my-extension-browser')
export class MyExtensionBrowserElement extends UmbLitElement {
#options: Option[] = [];
@state()
private _selectedExtensionType = 'dashboard';
@state()
private _selectedManifest = '';
constructor() {
super();
// Build list of available extension types from registry
this.observe(umbExtensionsRegistry.extensions, (extensions) => {
const types = [...new Set(extensions.map((x) => x.type))];
this.#options = types.sort().map((x) => ({
name: x,
value: x,
selected: x === this._selectedExtensionType,
}));
});
}
#onTypeSelect(event: UUISelectEvent) {
this._selectedManifest = '';
this._selectedExtensionType = event.target.value as string;
}
#onManifestChange(event: { target: UmbInputManifestElement }) {
const selectedManifest = event.target.value;
this._selectedManifest = selectedManifest?.value ?? '';
}
override render() {
return html`
<uui-box>
<umb-property-layout label="Extension Type">
<uui-select
slot="editor"
label="Select type"
placeholder="Select type..."
.options=${this.#options}
@change=${this.#onTypeSelect}
></uui-select>
</umb-property-layout>
${when(
this._selectedExtensionType,
() => html`
<umb-property-layout
label="Select Extension"
description="Pick a ${this._selectedExtensionType}"
>
<div slot="editor">
<umb-input-manifest
.extensionType=${this._selectedExtensionType}
@change=${this.#onManifestChange}
></umb-input-manifest>
</div>
</umb-property-layout>
`,
() => nothing
)}
${when(
this._selectedManifest,
() => html`
<umb-property-layout label="Selected Manifest">
<div slot="editor">
<code>${this._selectedManifest}</code>
</div>
</umb-property-layout>
`,
() => nothing
)}
</uui-box>
`;
}
}Getting All Extension Types
获取所有扩展类型
typescript
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
// In your element constructor
this.observe(umbExtensionsRegistry.extensions, (extensions) => {
// Get unique extension types
const types = [...new Set(extensions.map((x) => x.type))];
console.log('Available types:', types);
// Filter by type
const dashboards = extensions.filter((x) => x.type === 'dashboard');
console.log('Dashboards:', dashboards);
// Get extension by alias
const specific = extensions.find((x) => x.alias === 'Umb.Dashboard.Welcome');
console.log('Specific extension:', specific);
});typescript
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
// In your element constructor
this.observe(umbExtensionsRegistry.extensions, (extensions) => {
// Get unique extension types
const types = [...new Set(extensions.map((x) => x.type))];
console.log('Available types:', types);
// Filter by type
const dashboards = extensions.filter((x) => x.type === 'dashboard');
console.log('Dashboards:', dashboards);
// Get extension by alias
const specific = extensions.find((x) => x.alias === 'Umb.Dashboard.Welcome');
console.log('Specific extension:', specific);
});Common Extension Types
常见扩展类型
| Type | Description |
|---|---|
| Section dashboards |
| Entity workspaces |
| Views within workspaces |
| Workspace action buttons |
| Property editor UIs |
| Property editor schemas |
| Context menu actions |
| Navigation trees |
| Tree item renderers |
| Backoffice sections |
| Section views |
| Header bar apps |
| Modal dialogs |
| Extension conditions |
| Type | Description |
|---|---|
| 后台区域仪表板 |
| 实体工作区 |
| 工作区内视图 |
| 工作区操作按钮 |
| 属性编辑器UI |
| 属性编辑器架构 |
| 上下文菜单操作 |
| 导航树 |
| 树项渲染器 |
| 后台区域 |
| 区域视图 |
| 顶部栏应用 |
| 模态对话框 |
| 扩展条件 |
UmbInputManifest Properties
UmbInputManifest属性
| Property | Type | Description |
|---|---|---|
| | The type of extension to pick from |
| | The selected manifest |
| Property | Type | Description |
|---|---|---|
| | 要选择的扩展类型 |
| | 选中的manifest |
Events
事件
| Event | Detail | Description |
|---|---|---|
| | Fired when selection changes |
| Event | Detail | Description |
|---|---|---|
| | 当选择发生变化时触发 |
Accessing Selected Manifest Data
访问选中的Manifest数据
typescript
#onManifestChange(event: { target: UmbInputManifestElement }) {
const manifest = event.target.value;
if (manifest) {
console.log('Alias:', manifest.alias);
console.log('Name:', manifest.name);
console.log('Type:', manifest.type);
console.log('Full manifest:', manifest);
}
}typescript
#onManifestChange(event: { target: UmbInputManifestElement }) {
const manifest = event.target.value;
if (manifest) {
console.log('Alias:', manifest.alias);
console.log('Name:', manifest.name);
console.log('Type:', manifest.type);
console.log('Full manifest:', manifest);
}
}Use Cases
使用场景
- Configuration screens - Let users select which dashboard/workspace to show
- Extension management - Browse and inspect registered extensions
- Dynamic routing - Configure navigation targets
- Condition configuration - Select conditions to apply
- Package development - Test extension registration
- 配置界面 - 让用户选择要显示的仪表板/工作区
- 扩展管理 - 浏览和查看已注册的扩展
- 动态路由 - 配置导航目标
- 条件配置 - 选择要应用的条件
- 包开发 - 测试扩展注册
Best Practices
最佳实践
- Clear selection - Reset when type changes
_selectedManifest - Handle undefined - Check if exists before accessing properties
value - Use property layout - Wrap in for consistent styling
<umb-property-layout> - Show feedback - Display selected manifest alias/name to confirm selection
- Sort types - Sort extension type options alphabetically for usability
That's it! Always fetch fresh docs, keep examples minimal, generate complete working code.
- 清晰选择 - 当类型变化时重置
_selectedManifest - 处理未定义情况 - 在访问属性前检查是否存在
value - 使用属性布局 - 包裹在中以保持样式一致
<umb-property-layout> - 显示反馈 - 显示选中的manifest别名/名称以确认选择
- 排序类型 - 按字母顺序排序扩展类型选项以提升可用性
就是这样!请始终获取最新文档,保持示例简洁,生成完整的可运行代码。