-
Notifications
You must be signed in to change notification settings - Fork 810
Property Editor Data Source and Picker Data Source Type #7541
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
eshanrnh
merged 17 commits into
umbraco:main
from
madsrasmussen:v17/feature/property-editor-data-source
Oct 29, 2025
Merged
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
0325ac0
Add initial documentation for Property Editor Data Sources
madsrasmussen c90827b
add image
madsrasmussen 3c94783
add property editor + picker data source docs
madsrasmussen aebb503
update with data editor alias and razor examples
madsrasmussen 67c4bf9
Clarify example usage in Picker Data Source Type README
madsrasmussen 2d94abc
Clarify example usage in Data Source documentation
madsrasmussen d07d67d
Refine Property Editor Data Source documentation
madsrasmussen 3ce9969
Update SUMMARY.md
madsrasmussen c548984
Update property-editor-data-source.md
madsrasmussen 2687fda
Update property-editor-data-source.md
madsrasmussen 73ee48e
Update README.md
madsrasmussen af09907
Update 17/umbraco-cms/customizing/property-editors/composition/properβ¦
eshanrnh 47a7e17
Update 17/umbraco-cms/customizing/property-editors/composition/properβ¦
eshanrnh c496eb0
Update 17/umbraco-cms/customizing/property-editors/data-source-types/β¦
eshanrnh aa3a189
Update 17/umbraco-cms/customizing/property-editors/data-source-types/β¦
eshanrnh add873c
Update 17/umbraco-cms/fundamentals/backoffice/property-editors/built-β¦
eshanrnh 802738e
Update 17/umbraco-cms/SUMMARY.md
eshanrnh File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Binary file added
BIN
+27.4 KB
.gitbook/assets/umbraco-docs-data-type-property-editor-data-source.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
87 changes: 87 additions & 0 deletions
87
...aco-cms/customizing/property-editors/composition/property-editor-data-source.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| # Property Editor Data Source | ||
|
|
||
| A Property Editor Data Source is a way to provide data to a Property Editor UI. This allows for the reuse of the same UI across different data sources. | ||
|
|
||
| Data Sources are an opt-in feature for the Property Editor UI. When enabled, extensions can register Data Sources, which can be selected in the UI if their type is supported. | ||
|
|
||
| ## Enable Data Source Support | ||
|
|
||
| The Data Source support is enabled in the Property Editor UI manifest. Below is a snippet showing how to enable it. The `forDataSourceTypes` can include any already existing Data Source Types or new custom ones. | ||
|
|
||
| **Property Editor UI Manifest** | ||
|
|
||
| ```typescript | ||
| { | ||
| type: 'propertyEditorUi', | ||
| name: 'My Property Editor UI with Data Source support', | ||
| //... more | ||
| meta: { | ||
| //... more | ||
| supportsDataSource: { | ||
| enabled: true, | ||
| forDataSourceTypes: ['My.DataSourceType.Custom'] | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| When this feature is enabled, you can pick a Data Source in the Data Type Workspace next to the Property Editor field. The available Data Sources will match the supported Data Source Types of the chosen Property Editor UI. | ||
|
|
||
| <figure><img src="../../../.gitbook/assets/umbraco-docs-data-type-property-editor-data-source.png" alt=""><figcaption><p>Property Editor Data Source Picker</p></figcaption></figure> | ||
|
|
||
| ## Register a Property Editor Data Source | ||
|
|
||
| **Data Source Manifest** | ||
|
|
||
| ```typescript | ||
| { | ||
| type: 'propertyEditorDataSource', | ||
| dataSourceType: 'My.DataSourceType.Custom', | ||
| alias: 'Umb.PropertyEditorDataSource.MyCustomDataSource', | ||
| name: 'My Custom Data Source', | ||
| api: () => import('./my-custom-data-source.js'), | ||
| meta: { | ||
| label: 'My Data', | ||
| description: 'A good description of the data', | ||
| icon: 'icon-database', | ||
| }, | ||
| }, | ||
| ``` | ||
|
|
||
| ### Data Source Settings | ||
|
|
||
| Like Property Editor UIs and Schemas, Data Sources can have settings for configuration of the data source. These settings are defined in the manifest under `meta.settings`. The settings for a Data Source will be rendered in the Data Type Workspace together with the Property Editor UI and Schema settings. | ||
|
|
||
| **Data Source Manifest** | ||
|
|
||
| ```typescript | ||
| { | ||
| type: 'propertyEditorDataSource', | ||
| alias: 'Umb.PropertyEditorDataSource.MyCustomDataSource', | ||
| //... more | ||
| meta: { | ||
| //... more | ||
| settings: { | ||
| properties: [], | ||
| }, | ||
| }, | ||
| }; | ||
| ``` | ||
|
|
||
| ## Access Data Source Alias in Property Editor UI | ||
|
|
||
| When implementing a Property Editor UI element, the Data Source alias can be accessed through the `dataSourceAlias` property. | ||
|
|
||
| ```typescript | ||
| interface UmbPropertyEditorUiElement extends HTMLElement { | ||
| dataSourceAlias?: string; | ||
| } | ||
| ``` | ||
|
|
||
| ## Access Data Source Config in Property Editor UI | ||
|
|
||
| The Data Source configuration can be accessed through the `config` property of the Property Editor UI element merged with the UI and Schema config. | ||
|
|
||
| ## Built-in Data Source Types | ||
|
|
||
| - [Picker](../data-source-types/picker/README.md) - Used by Property Editors that pick entities, for example, the Entity Data Picker Property Editor. |
27 changes: 27 additions & 0 deletions
27
17/umbraco-cms/customizing/property-editors/data-source-types/picker/README.md
madsrasmussen marked this conversation as resolved.
Show resolved
Hide resolved
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| # Picker Data Source Type | ||
|
|
||
| The `Umb.DataSourceType.Picker` Data Source Type is used by Property Editors that pick entities, for example, the built-in [Entity Data Picker Property Editor](../../../../fundamentals/backoffice/property-editors/built-in-umbraco-property-editors/entity-data-picker.md). | ||
|
|
||
| ## Register a Picker Data Source | ||
|
|
||
| **Data Source Manifest** | ||
|
|
||
| ```typescript | ||
| { | ||
| type: 'propertyEditorDataSource', | ||
| dataSourceType: 'Umb.DataSourceType.Picker', | ||
| alias: 'Umb.PropertyEditorDataSource.MyPickerDataSource', | ||
| name: 'My Picker Data Source', | ||
| api: () => import('./my-picker-data-source.js'), | ||
| meta: { | ||
| label: 'My Data Source', | ||
| description: 'A good description of the data source', | ||
| icon: 'icon-database', | ||
| }, | ||
| }, | ||
| ``` | ||
|
|
||
| The Picker Data Source supports two types of data structures: | ||
|
|
||
| - [Collection Data](./picker-collection-data-source.md) | ||
| - [Tree Data](./picker-tree-data-source.md) |
88 changes: 88 additions & 0 deletions
88
...zing/property-editors/data-source-types/picker/picker-collection-data-source.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| ## Picker Collection Data Source | ||
|
|
||
| The interface below is simplified for clarity and omits return types and arguments. See full interfaces in the [UI API Documentation](https://apidocs.umbraco.com/v17/ui-api/modules/packages_core_picker-data-source.html) | ||
|
|
||
| ```typescript | ||
| interface UmbPickerPropertyEditorCollectionDataSource { | ||
| requestCollection(); | ||
| requestItems(); | ||
| search?(); | ||
| setConfig?(); | ||
| getConfig?(); | ||
| } | ||
| ``` | ||
|
|
||
| ### Example | ||
| ```typescript | ||
| import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; | ||
| import type { UmbCollectionFilterModel, UmbCollectionItemModel } from '@umbraco-cms/backoffice/collection'; | ||
| import type { | ||
| UmbPickerCollectionDataSource, | ||
| UmbPickerSearchableDataSource, | ||
| } from '@umbraco-cms/backoffice/picker-data-source'; | ||
| import type { UmbSearchRequestArgs } from '@umbraco-cms/backoffice/search'; | ||
|
|
||
| interface ExampleCollectionItemModel extends UmbCollectionItemModel { | ||
| isPickable: boolean; | ||
| } | ||
|
|
||
| export class MyCustomPickerCollectionPropertyEditorDataSource | ||
| extends UmbControllerBase | ||
| implements UmbPickerCollectionDataSource<ExampleCollectionItemModel>, UmbPickerSearchableDataSource | ||
| { | ||
| collectionPickableFilter = (item: ExampleCollectionItemModel) => item.isPickable; | ||
|
|
||
| async requestCollection(args: UmbCollectionFilterModel) { | ||
| const data = { | ||
| items: customItems, | ||
| total: customItems.length, | ||
| }; | ||
|
|
||
| return { data }; | ||
| } | ||
|
|
||
| async requestItems(uniques: Array<string>) { | ||
| const items = customItems.filter((x) => uniques.includes(x.unique)); | ||
| return { data: items }; | ||
| } | ||
|
|
||
| async search(args: UmbSearchRequestArgs) { | ||
| const items = customItems.filter((item) => item.name?.toLowerCase().includes(args.query.toLowerCase())); | ||
| const total = items.length; | ||
|
|
||
| const data = { | ||
| items, | ||
| total, | ||
| }; | ||
|
|
||
| return { data }; | ||
| } | ||
| } | ||
|
|
||
| export { ExampleCustomPickerCollectionPropertyEditorDataSource as api }; | ||
|
|
||
| const customItems: Array<ExampleCollectionItemModel> = [ | ||
| { | ||
| unique: '1', | ||
| entityType: 'example', | ||
| name: 'Example 1', | ||
| icon: 'icon-shape-triangle', | ||
| isPickable: true, | ||
| }, | ||
| { | ||
| unique: '2', | ||
| entityType: 'example', | ||
| name: 'Example 2', | ||
| icon: 'icon-shape-triangle', | ||
| isPickable: false, | ||
| }, | ||
| { | ||
| unique: '3', | ||
| entityType: 'example', | ||
| name: 'Example 3', | ||
| icon: 'icon-shape-triangle', | ||
| isPickable: true, | ||
| }, | ||
| ]; | ||
|
|
||
| ``` |
156 changes: 156 additions & 0 deletions
156
...ustomizing/property-editors/data-source-types/picker/picker-tree-data-source.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,156 @@ | ||
| ## Picker Tree Data Source | ||
|
|
||
| The interface below is simplified for clarity and omits return types and arguments. See full interfaces in the [UI API Documentation](https://apidocs.umbraco.com/v17/ui-api/modules/packages_core_picker-data-source.html) | ||
|
|
||
|
|
||
| ```typescript | ||
| interface UmbPickerPropertyEditorCollectionDataSource { | ||
| requestTreeRoot(); | ||
| requestTreeRootItems(); | ||
| requestTreeItemsOf(); | ||
| requestTreeItemAncestors(); | ||
| requestItems(); | ||
| search?(); | ||
| setConfig?(); | ||
| getConfig?(); | ||
| } | ||
| ``` | ||
|
|
||
|
|
||
| ### Example | ||
| ```typescript | ||
| import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; | ||
| import type { | ||
| UmbPickerSearchableDataSource, | ||
| UmbPickerTreeDataSource, | ||
| } from '@umbraco-cms/backoffice/picker-data-source'; | ||
| import type { UmbSearchRequestArgs, UmbSearchResultItemModel } from '@umbraco-cms/backoffice/search'; | ||
| import type { UmbTreeChildrenOfRequestArgs, UmbTreeItemModel } from '@umbraco-cms/backoffice/tree'; | ||
|
|
||
| export class ExampleCustomPickerTreePropertyEditorDataSource | ||
| extends UmbControllerBase | ||
| implements UmbPickerTreeDataSource, UmbPickerSearchableDataSource | ||
| { | ||
| treePickableFilter: (treeItem: UmbTreeItemModel) => boolean = (treeItem) => | ||
| !!treeItem.unique && treeItem.entityType === 'example'; | ||
|
|
||
| searchPickableFilter: (searchItem: UmbSearchResultItemModel) => boolean = (searchItem) => | ||
| !!searchItem.unique && searchItem.entityType === 'example'; | ||
|
|
||
| async requestTreeRoot() { | ||
| const root = { | ||
| unique: null, | ||
| name: 'Examples', | ||
| icon: 'icon-folder', | ||
| hasChildren: true, | ||
| entityType: 'example-root', | ||
| isFolder: true, | ||
| }; | ||
|
|
||
| return { data: root }; | ||
| } | ||
|
|
||
| async requestTreeRootItems() { | ||
| const rootItems = customItems.filter((item) => item.parent.unique === null); | ||
|
|
||
| const data = { | ||
| items: rootItems, | ||
| total: rootItems.length, | ||
| }; | ||
|
|
||
| return { data }; | ||
| } | ||
|
|
||
| async requestTreeItemsOf(args: UmbTreeChildrenOfRequestArgs) { | ||
| const items = customItems.filter( | ||
| (item) => item.parent.entityType === args.parent.entityType && item.parent.unique === args.parent.unique, | ||
| ); | ||
|
|
||
| const data = { | ||
| items: items, | ||
| total: items.length, | ||
| }; | ||
|
|
||
| return { data }; | ||
| } | ||
|
|
||
| async requestTreeItemAncestors() { | ||
| // TODO: implement when needed | ||
| return { data: [] }; | ||
| } | ||
|
|
||
| async requestItems(uniques: Array<string>) { | ||
| const items = customItems.filter((x) => uniques.includes(x.unique)); | ||
| return { data: items }; | ||
| } | ||
|
|
||
| async search(args: UmbSearchRequestArgs) { | ||
| const result = customItems.filter((item) => item.name.toLowerCase().includes(args.query.toLowerCase())); | ||
|
|
||
| const data = { | ||
| items: result, | ||
| total: result.length, | ||
| }; | ||
|
|
||
| return { data }; | ||
| } | ||
| } | ||
|
|
||
| export { ExampleCustomPickerTreePropertyEditorDataSource as api }; | ||
|
|
||
| const customItems: Array<UmbTreeItemModel> = [ | ||
| { | ||
| unique: '1', | ||
| entityType: 'example', | ||
| name: 'Example 1', | ||
| icon: 'icon-shape-triangle', | ||
| parent: { unique: null, entityType: 'example-root' }, | ||
| isFolder: false, | ||
| hasChildren: false, | ||
| }, | ||
| { | ||
| unique: '2', | ||
| entityType: 'example', | ||
| name: 'Example 2', | ||
| icon: 'icon-shape-triangle', | ||
| parent: { unique: null, entityType: 'example-root' }, | ||
| isFolder: false, | ||
| hasChildren: false, | ||
| }, | ||
| { | ||
| unique: '3', | ||
| entityType: 'example', | ||
| name: 'Example 3', | ||
| icon: 'icon-shape-triangle', | ||
| parent: { unique: null, entityType: 'example-root' }, | ||
| isFolder: false, | ||
| hasChildren: false, | ||
| }, | ||
| { | ||
| unique: '4', | ||
| entityType: 'example', | ||
| name: 'Example 4', | ||
| icon: 'icon-shape-triangle', | ||
| parent: { unique: '6', entityType: 'example-folder' }, | ||
| isFolder: false, | ||
| hasChildren: false, | ||
| }, | ||
| { | ||
| unique: '5', | ||
| entityType: 'example', | ||
| name: 'Example 5', | ||
| icon: 'icon-shape-triangle', | ||
| parent: { unique: '6', entityType: 'example-folder' }, | ||
| isFolder: false, | ||
| hasChildren: false, | ||
| }, | ||
| { | ||
| unique: '6', | ||
| entityType: 'example-folder', | ||
| name: 'Example Folder 1', | ||
| parent: { unique: null, entityType: 'example-root' }, | ||
| isFolder: true, | ||
| hasChildren: true, | ||
| }, | ||
| ]; | ||
| ``` |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.