Skip to main content
umbraco-collection Implement collections in Umbraco backoffice using official docs
설치로 이동 Skills Marketplace 커뮤니티가 만든 AI 스킬을 발견하고 탐색하세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/umbraco/Umbraco-CMS-Backoffice-Skills --skill umbraco-collection명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
Zip 다운로드 다운로드 중... SOC
name umbraco-collection description Implement collections in Umbraco backoffice using official docs version 1.1.0 location managed allowed-tools Read, Write, Edit, WebFetch
Umbraco Collection
What is it?
A Collection displays a list of entities in the Umbraco backoffice with built-in support for multiple views (table, grid), filtering, pagination, selection, and bulk actions. Collections connect to a repository for data and provide a standardized way to browse and interact with lists of items.
Documentation
Always fetch the latest docs before implementing:
Collection Architecture A complete collection consists of these components:
collection/
├── manifests.ts # Main collection manifest
├── constants.ts # Alias constants
├── types.ts # Item and filter types
├── my-collection.context.ts # Collection context (extends UmbDefaultCollectionContext)
├── my-collection.element.ts # Collection element (extends UmbCollectionDefaultElement)
├── repository/
│ ├── manifests.ts
│ ├── my-collection.repository.ts # Implements UmbCollectionRepository
│ └── my-collection.data-source.ts # API calls
├── views/
│ ├── manifests.ts
│ └── table/
│ └── my-table-view.element.ts # Table view
└── action/
├── manifests.ts
└── my-action.element.ts # Collection action
Reference Example The Umbraco source includes a working example:
Location : /Umbraco-CMS/src/Umbraco.Web.UI.Client/examples/collection/
This example demonstrates a complete custom collection with repository, views, and context. Study this for production patterns.
Related Foundation Skills
Repository Pattern : Collections require a repository for data access
Reference skill: umbraco-repository-pattern
Context API : For accessing collection context in views
Reference skill: umbraco-context-api
State Management : For understanding observables and reactive data
Reference skill: umbraco-state-management
Workflow
Fetch docs - Use WebFetch on the URLs above
Ask questions - What entities? What repository? What views needed? What actions?
Define types - Create item model and filter model interfaces
Create repository - Implement data source and repository
Create context - Extend UmbDefaultCollectionContext if custom behavior needed
Create views - Implement table/grid views
Create actions - Add collection actions (create, refresh, etc.)
Explain - Show what was created and how to test
Complete Example
1. Constants (constants.ts) export const MY_COLLECTION_ALIAS = 'My.Collection' ;
export const MY_COLLECTION_REPOSITORY_ALIAS = 'My.Collection.Repository' ;
2. Types (types.ts) export interface MyCollectionItemModel {
unique : string ;
entityType : string ;
name : string ;
}
export interface MyCollectionFilterModel {
skip ?: number ;
take ?: number ;
filter ?: string ;
orderBy ?: string ;
orderDirection ?: 'asc' | 'desc' ;
}
3. Data Source (repository/my-collection.data-source.ts) import type { MyCollectionItemModel , MyCollectionFilterModel } from '../types.js' ;
import type { UmbCollectionDataSource } from '@umbraco-cms/backoffice/collection' ;
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api' ;
export class MyCollectionDataSource implements UmbCollectionDataSource <MyCollectionItemModel > {
#host : UmbControllerHost ;
constructor (host : UmbControllerHost ) {
this .#host = host;
}
async getCollection (filter : MyCollectionFilterModel ) {
const response = await fetch (`/api/my-items?skip=${filter.skip} &take=${filter.take} ` );
const data = await response.json ();
const items : MyCollectionItemModel [] = data.items .map ((item : any ) => ({
unique : item.id ,
entityType : 'my-entity' ,
name : item.name ,
}));
return { data : { items, total : data.total } };
}
}
4. Repository (repository/my-collection.repository.ts) import type { MyCollectionFilterModel } from '../types.js' ;
import { MyCollectionDataSource } from './my-collection.data-source.js' ;
import { UmbRepositoryBase } from '@umbraco-cms/backoffice/repository' ;
import type { UmbCollectionRepository } from '@umbraco-cms/backoffice/collection' ;
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api' ;
export class MyCollectionRepository extends UmbRepositoryBase implements UmbCollectionRepository {
#dataSource : MyCollectionDataSource ;
constructor (host : UmbControllerHost ) {
super (host);
this .#dataSource = new MyCollectionDataSource (host);
}
async requestCollection (filter : MyCollectionFilterModel ) {
return this .#dataSource.getCollection (filter);
}
}
export default MyCollectionRepository ;
5. Repository Manifest (repository/manifests.ts) import { MY_COLLECTION_REPOSITORY_ALIAS } from '../constants.js' ;
export const manifests : Array <UmbExtensionManifest > = [
{
type : 'repository' ,
alias : MY_COLLECTION_REPOSITORY_ALIAS ,
name : 'My Collection Repository' ,
api : () => import ('./my-collection.repository.js' ),
},
];
6. Collection Context (my-collection.context.ts) import type { MyCollectionItemModel , MyCollectionFilterModel } from './types.js' ;
import { UmbDefaultCollectionContext } from '@umbraco-cms/backoffice/collection' ;
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api' ;
const MY_TABLE_VIEW_ALIAS = 'My.CollectionView.Table' ;
export class MyCollectionContext extends UmbDefaultCollectionContext <
MyCollectionItemModel ,
MyCollectionFilterModel
> {
constructor (host : UmbControllerHost ) {
super (host, MY_TABLE_VIEW_ALIAS );
}
}
export { MyCollectionContext as api };
7. Collection Element (my-collection.element.ts) import { customElement } from '@umbraco-cms/backoffice/external/lit' ;
import { UmbCollectionDefaultElement } from '@umbraco-cms/backoffice/collection' ;
@customElement ('my-collection' )
export class MyCollectionElement extends UmbCollectionDefaultElement {
}
export default MyCollectionElement ;
export { MyCollectionElement as element };
declare global {
interface HTMLElementTagNameMap {
'my-collection' : MyCollectionElement ;
}
}
8. Table View (views/table/my-table-view.element.ts) import type { MyCollectionItemModel } from '../../types.js' ;
import { UMB_COLLECTION_CONTEXT } from '@umbraco-cms/backoffice/collection' ;
import { css, customElement, html, state } from '@umbraco-cms/backoffice/external/lit' ;
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element' ;
import type { UmbTableColumn , UmbTableConfig , UmbTableItem } from '@umbraco-cms/backoffice/components' ;
@customElement ('my-table-collection-view' )
export class MyTableCollectionViewElement extends UmbLitElement {
@state ()
private _tableItems : Array <UmbTableItem > = [];
@state ()
private _selection : Array <string > = [];
#collectionContext ?: typeof UMB_COLLECTION_CONTEXT .TYPE ;
private _tableConfig : UmbTableConfig = {
allowSelection : true ,
};
private _tableColumns : Array <UmbTableColumn > = [
{ name : 'Name' , alias : 'name' , allowSorting : true },
{ name : '' , alias : 'entityActions' , align : 'right' },
];
constructor ( ) {
super ();
this .consumeContext (UMB_COLLECTION_CONTEXT , (context ) => {
this .#collectionContext = context;
context?.setupView (this );
this .#observeItems ();
this .#observeSelection ();
});
}
#observeItems ( ) {
if (!this .#collectionContext) return ;
this .observe (
this .#collectionContext.items ,
(items ) => {
this ._tableItems = (items as MyCollectionItemModel []).map ((item ) => ({
id : item.unique ,
icon : 'icon-document' ,
entityType : item.entityType ,
data : [
{ columnAlias : 'name' , value : item.name },
{
columnAlias : 'entityActions' ,
value : html`<umb-entity-actions-table-column-view
.value = ${{ entityType: item.entityType, unique: item.unique }}
> </umb-entity-actions-table-column-view > ` ,
},
],
}));
},
'_observeItems' ,
);
}
#observeSelection ( ) {
if (!this .#collectionContext) return ;
this .observe (
this .#collectionContext.selection .selection ,
(selection ) => {
this ._selection = selection as string [];
},
'_observeSelection' ,
);
}
#handleSelect (event : CustomEvent ) {
event.stopPropagation ();
const table = event.target as any ;
this .#collectionContext?.selection .setSelection (table.selection );
}
#handleDeselect (event : CustomEvent ) {
event.stopPropagation ();
const table = event.target as any ;
this .#collectionContext?.selection .setSelection (table.selection );
}
override render ( ) {
return html`
<umb-table
.config = ${this ._tableConfig}
.columns = ${this ._tableColumns}
.items = ${this ._tableItems}
.selection = ${this ._selection}
@selected = ${this .#handleSelect}
@deselected = ${this .#handleDeselect}
> </umb-table >
` ;
}
}
export default MyTableCollectionViewElement ;
declare global {
interface HTMLElementTagNameMap {
'my-table-collection-view' : MyTableCollectionViewElement ;
}
}
9. Views Manifest (views/manifests.ts) import { MY_COLLECTION_ALIAS } from '../constants.js' ;
import { UMB_COLLECTION_ALIAS_CONDITION } from '@umbraco-cms/backoffice/collection' ;
export const manifests : Array <UmbExtensionManifest > = [
{
type : 'collectionView' ,
alias : 'My.CollectionView.Table' ,
name : 'My Table Collection View' ,
element : () => import ('./table/my-table-view.element.js' ),
weight : 200 ,
meta : {
label : 'Table' ,
icon : 'icon-list' ,
pathName : 'table' ,
},
conditions : [
{
alias : UMB_COLLECTION_ALIAS_CONDITION ,
match : MY_COLLECTION_ALIAS ,
},
],
},
];
10. Collection Action (action/manifests.ts) import { MY_COLLECTION_ALIAS } from '../constants.js' ;
import { UMB_COLLECTION_ALIAS_CONDITION } from '@umbraco-cms/backoffice/collection' ;
export const manifests : Array <UmbExtensionManifest > = [
{
type : 'collectionAction' ,
kind : 'button' ,
alias : 'My.CollectionAction.Refresh' ,
name : 'Refresh Collection Action' ,
element : () => import ('./refresh-action.element.js' ),
weight : 100 ,
meta : {
label : 'Refresh' ,
},
conditions : [
{
alias : UMB_COLLECTION_ALIAS_CONDITION ,
match : MY_COLLECTION_ALIAS ,
},
],
},
];
11. Main Collection Manifest (manifests.ts) import { manifests as repositoryManifests } from './repository/manifests.js' ;
import { manifests as viewManifests } from './views/manifests.js' ;
import { manifests as actionManifests } from './action/manifests.js' ;
import { MY_COLLECTION_ALIAS , MY_COLLECTION_REPOSITORY_ALIAS } from './constants.js' ;
export const manifests : Array <UmbExtensionManifest > = [
{
type : 'collection' ,
alias : MY_COLLECTION_ALIAS ,
name : 'My Collection' ,
api : () => import ('./my-collection.context.js' ),
element : () => import ('./my-collection.element.js' ),
meta : {
repositoryAlias : MY_COLLECTION_REPOSITORY_ALIAS ,
},
},
...repositoryManifests,
...viewManifests,
...actionManifests,
];
Rendering a Collection in a Dashboard import { html, customElement } from '@umbraco-cms/backoffice/external/lit' ;
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element' ;
@customElement ('my-dashboard' )
export class MyDashboardElement extends UmbLitElement {
override render ( ) {
return html`<umb-collection alias ="My.Collection" > </umb-collection > ` ;
}
}
Built-in Features The collection system provides these features automatically:
Feature Description Selection UmbSelectionManager on context.selectionPagination UmbPaginationManager on context.paginationLoading state Observable via context.loading Items Observable via context.items Total count Observable via context.totalItems Filtering Via context.setFilter() method View switching Multiple views with UmbCollectionViewManager
Key Condition Use UMB_COLLECTION_ALIAS_CONDITION to target your collection:
import { UMB_COLLECTION_ALIAS_CONDITION } from '@umbraco-cms/backoffice/collection' ;
conditions : [
{
alias : UMB_COLLECTION_ALIAS_CONDITION ,
match : 'My.Collection' ,
},
],
That's it! Always fetch fresh docs, keep examples minimal, generate complete working code.