diff --git a/.gitbook/assets/umbraco-docs-data-type-property-editor-data-source.png b/.gitbook/assets/umbraco-docs-data-type-property-editor-data-source.png new file mode 100644 index 00000000000..ee115854692 Binary files /dev/null and b/.gitbook/assets/umbraco-docs-data-type-property-editor-data-source.png differ diff --git a/17/umbraco-cms/SUMMARY.md b/17/umbraco-cms/SUMMARY.md index f43de56b210..fbaa8a7e65b 100644 --- a/17/umbraco-cms/SUMMARY.md +++ b/17/umbraco-cms/SUMMARY.md @@ -64,6 +64,7 @@ * [Date Time (Unspecified)](fundamentals/backoffice/property-editors/built-in-umbraco-property-editors/date-time-editor/date-time-unspecified.md) * [Decimal](fundamentals/backoffice/property-editors/built-in-umbraco-property-editors/decimal.md) * [Email Address](fundamentals/backoffice/property-editors/built-in-umbraco-property-editors/email-address.md) + * [Entity Data Picker](fundamentals/backoffice/property-editors/built-in-umbraco-property-editors/entity-data-picker.md) * [Eye Dropper Color Picker](fundamentals/backoffice/property-editors/built-in-umbraco-property-editors/eye-dropper-color-picker.md) * [File Upload](fundamentals/backoffice/property-editors/built-in-umbraco-property-editors/file-upload.md) * [Image Cropper](fundamentals/backoffice/property-editors/built-in-umbraco-property-editors/image-cropper.md) @@ -227,6 +228,11 @@ * [Property Editors Composition](customizing/property-editors/composition/README.md) * [Property Editor Schema](customizing/property-editors/composition/property-editor-schema.md) * [Property Editor UI](customizing/property-editors/composition/property-editor-ui.md) + * [Property Editor Data Source](customizing/property-editors/composition/property-editor-data-source.md) + * Property Editor Data Source Types + * [Picker Data Source Type](customizing/property-editors/data-source-types/picker/README.md) + * [Collection Data Source](customizing/property-editors/data-source-types/picker/picker-collection-data-source.md) + * [Tree Data Source](customizing/property-editors/data-source-types/picker/picker-tree-data-source.md) * [Property Value Converters](customizing/property-editors/property-value-converters.md) * [Property Value Converter Example](customizing/property-editors/full-examples-value-converters.md) * [Property Actions](customizing/property-editors/property-actions.md) diff --git a/17/umbraco-cms/customizing/property-editors/composition/README.md b/17/umbraco-cms/customizing/property-editors/composition/README.md index f0298a26a69..1305f631b49 100644 --- a/17/umbraco-cms/customizing/property-editors/composition/README.md +++ b/17/umbraco-cms/customizing/property-editors/composition/README.md @@ -22,3 +22,8 @@ A Property Editor UI is utilizing a Property Editor Schema, and you can have mul * Data Type Settings for a Property Editor or Property Editor UI is defined in the manifests. * They both use the same format for their settings. + +## Property Editor Data Sources +A Property Editor Data Source is an optional way to provide data to a Property Editor UI. This allows for reuse of the same Property Editor UI but with different data sources. + +* [Property Editor Data Source](property-editor-data-source.md) diff --git a/17/umbraco-cms/customizing/property-editors/composition/property-editor-data-source.md b/17/umbraco-cms/customizing/property-editors/composition/property-editor-data-source.md new file mode 100644 index 00000000000..1fc8197ef7a --- /dev/null +++ b/17/umbraco-cms/customizing/property-editors/composition/property-editor-data-source.md @@ -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. + +

Property Editor Data Source Picker

+ +## 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. diff --git a/17/umbraco-cms/customizing/property-editors/data-source-types/picker/README.md b/17/umbraco-cms/customizing/property-editors/data-source-types/picker/README.md new file mode 100644 index 00000000000..b542f7a9d05 --- /dev/null +++ b/17/umbraco-cms/customizing/property-editors/data-source-types/picker/README.md @@ -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) diff --git a/17/umbraco-cms/customizing/property-editors/data-source-types/picker/picker-collection-data-source.md b/17/umbraco-cms/customizing/property-editors/data-source-types/picker/picker-collection-data-source.md new file mode 100644 index 00000000000..88f39313858 --- /dev/null +++ b/17/umbraco-cms/customizing/property-editors/data-source-types/picker/picker-collection-data-source.md @@ -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, UmbPickerSearchableDataSource +{ + collectionPickableFilter = (item: ExampleCollectionItemModel) => item.isPickable; + + async requestCollection(args: UmbCollectionFilterModel) { + const data = { + items: customItems, + total: customItems.length, + }; + + return { data }; + } + + async requestItems(uniques: Array) { + 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 = [ + { + 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, + }, +]; + +``` \ No newline at end of file diff --git a/17/umbraco-cms/customizing/property-editors/data-source-types/picker/picker-tree-data-source.md b/17/umbraco-cms/customizing/property-editors/data-source-types/picker/picker-tree-data-source.md new file mode 100644 index 00000000000..f488437966e --- /dev/null +++ b/17/umbraco-cms/customizing/property-editors/data-source-types/picker/picker-tree-data-source.md @@ -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) { + 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 = [ + { + 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, + }, +]; +``` \ No newline at end of file diff --git a/17/umbraco-cms/fundamentals/backoffice/property-editors/built-in-umbraco-property-editors/entity-data-picker.md b/17/umbraco-cms/fundamentals/backoffice/property-editors/built-in-umbraco-property-editors/entity-data-picker.md new file mode 100644 index 00000000000..0f7c8c3fd87 --- /dev/null +++ b/17/umbraco-cms/fundamentals/backoffice/property-editors/built-in-umbraco-property-editors/entity-data-picker.md @@ -0,0 +1,75 @@ +# Entity Data Picker + +`Schema Alias: Umbraco.EntityDataPicker` + +`UI Alias: Umb.PropertyEditorUi.EntityDataPicker` + +`Returns: Umbraco.Cms.Core.Models.EntityDataPickerValue` + +`Supported Data Source Types:` [Picker](../../../../customizing/property-editors/data-source-types/picker/README.md) + +The Entity Data Picker property editor allows editors to pick one or more entities from a configurable data source. The selected entities are stored as an array of strings, where each string represents the ID of the selected entity. + +### With Models Builder + +```razor +@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage +@{ + Layout = null; +} + + + Entity Data Picker + + +@if (Model.MyEntityPicker is null) +{ +

No entity picker value found

+} +else +{ +

Data source: @Model.MyEntityPicker.DataSource

+

Picked IDs:

+
    + @foreach (string id in Model.MyEntityPicker.Ids) + { +
  • @id
  • + } +
+} + + +``` + +### Without Models Builder + +```razor +@using Umbraco.Cms.Core.Models +@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage +@{ + Layout = null; + var entityDataPickerValue = Model.Value("myEntityPicker"); +} + + + Entity Data Picker + + +@if (entityDataPickerValue is null) +{ +

No entity picker value found

+} +else +{ +

Data source: @entityDataPickerValue.DataSource

+

Picked IDs:

+
    + @foreach (string id in @entityDataPickerValue.Ids) + { +
  • @id
  • + } +
+} + + +```