From 10b8377c4f1eb1ecaa802b53e783fa217a9a5834 Mon Sep 17 00:00:00 2001 From: Ben Szymanski Date: Thu, 25 Sep 2025 15:34:32 +0200 Subject: [PATCH 1/4] Revised Global Contexts section for clarity and added best practices guidance. --- .../extension-types/global-context.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/16/umbraco-cms/customizing/extending-overview/extension-types/global-context.md b/16/umbraco-cms/customizing/extending-overview/extension-types/global-context.md index 744314d195c..fc8b01461fd 100644 --- a/16/umbraco-cms/customizing/extending-overview/extension-types/global-context.md +++ b/16/umbraco-cms/customizing/extending-overview/extension-types/global-context.md @@ -1,20 +1,20 @@ --- -description: Establish the bond for extensions to communication across the application +description: Establish the bond for extensions to communication between packages and across the application --- # Global Context -{% hint style="warning" %} -This page is a work in progress and may undergo further revisions, updates, or amendments. The information contained herein is subject to change without notice. -{% endhint %} +Global Context extension types allow extension authors to extract out shared logic code and make it available across the entire backoffice. These contexts are kept alive through the entire backoffice session. -A global context manages the logic code from your Lit Element controllers. +Global Contexts are useful when a package needs to share functionality with other package authors. + +Extension authors should prefer to use other context types [Workspace Contexts](workspaces/workspace-context.md) over Global Contexts. Umbraco itself uses Global Contexts sparingly, for clipboard, current user, and icons. ## Registration of a Global Context You can register a global context like so: -```typescript +```json { type: 'globalContext', alias: 'My.GlobalContext.Products', From 77a996d793e685818c180f273f97aad5470f295f Mon Sep 17 00:00:00 2001 From: Ben Szymanski Date: Tue, 7 Oct 2025 11:59:22 -0500 Subject: [PATCH 2/4] Rewrote global context article to include insights from community meetup, examples of how to create a context and how to consume a context. --- .../extension-types/global-context.md | 143 +++++++++++++++++- 1 file changed, 135 insertions(+), 8 deletions(-) diff --git a/16/umbraco-cms/customizing/extending-overview/extension-types/global-context.md b/16/umbraco-cms/customizing/extending-overview/extension-types/global-context.md index fc8b01461fd..b800d89461a 100644 --- a/16/umbraco-cms/customizing/extending-overview/extension-types/global-context.md +++ b/16/umbraco-cms/customizing/extending-overview/extension-types/global-context.md @@ -1,24 +1,151 @@ --- -description: Establish the bond for extensions to communication between packages and across the application +description: Global contexts in Umbraco provide a clean, type-safe way to share functionality across the backoffice. --- # Global Context -Global Context extension types allow extension authors to extract out shared logic code and make it available across the entire backoffice. These contexts are kept alive through the entire backoffice session. +The Global Context extension type allows extension authors to create a custom context of data and functions and make it available across the entire backoffice. Unlike other contexts that might be scoped to a specific workspace or view, a global context is available everywhere. These contexts are kept alive through the entire backoffice session. -Global Contexts are useful when a package needs to share functionality with other package authors. +Consider using a global context when you need to: + +- **Share state across multiple extensions** - Track user preferences or application-wide settings +- **Provide utility functions** - Common operations that multiple parts of an extension +- **Manage centralized services** - API clients, notification handlers, or data repositories +- **Coordinate between different extensions** - Communication layer between dashboards, property editors, and other components +- **Share functionality with other extensions** - Allow other package developers to access features and functionality within the package Extension authors should prefer to use other context types [Workspace Contexts](workspaces/workspace-context.md) over Global Contexts. Umbraco itself uses Global Contexts sparingly, for clipboard, current user, and icons. ## Registration of a Global Context -You can register a global context like so: +Global Context extensions can be registered using a manifest file like `umbraco-package.json`. +{% code title="umbraco-package.json" %} ```json { - type: 'globalContext', - alias: 'My.GlobalContext.Products', - name: 'My Products Context', - api: 'my-products.context.js', + "$schema": "../../umbraco-package-schema.json", + "name": "My Global Context Package", + "version": "1.0.0", + "extensions": [ + { + "type": "globalContext", + "alias": "My.GlobalContext", + "name": "My Global Context", + "api": "/App_Plugins/my-global-context/dist/my-context.context.js" + } + ] +} +``` +{% endcode %} + +**Key fields:** +- `type`: Must be `"globalContext"`, see: [ManifestGlobalContext](https://apidocs.umbraco.com/v16/ui-api/interfaces/packages_core_extension-registry.ManifestGlobalContext.html) +- `alias`: A unique identifier for the context +- `name`: A human-readable name +- `api`: The path to the compiled JavaScript file + +## Creating Your Global Context + +### 1. Define a Context Token + +First, create a context token. This is how other parts of an extension will reference the context: + +{% code title="src/my-context.ts" %} +```typescript +import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; + +export interface MyGlobalContextInterface { + getCurrentUser(): Promise; + setPreference(key: string, value: any): void; + getPreference(key: string): any; + getHostElement(): Element; +} + +export const MY_GLOBAL_CONTEXT = new UmbContextToken( + 'My.GlobalContext' +); +``` +{% endcode %} + +### 2. Implement the Context Class + +Next, implement the context class: + +{% code title="src/my-context.ts" %} +```typescript +import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; +import { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; + +export class MyGlobalContext extends UmbContextBase implements MyGlobalContextInterface { + #preferences: Map = new Map(); + + constructor(host: UmbControllerHost) { + super(host, MY_GLOBAL_CONTEXT); + } + + async getCurrentUser(): Promise { + // In a real implementation, you'd fetch this from the API + return 'Current User'; + } + + setPreference(key: string, value: any): void { + this.#preferences.set(key, value); + console.log(`Preference set: ${key} = ${value}`); + } + + getPreference(key: string): any { + return this.#preferences.get(key); + } + + getHostElement(): Element { + return this; + } +} + +export default MyGlobalContext; +``` +{% endcode %} + +## Using Global Contexts + +Once the global context extension is registered, it can be consumed in any web component throughout the backoffice. + +{% code title="src/my-custom-dashboard.ts" %} +```typescript +import { LitElement, html, customElement } from '@umbraco-cms/backoffice/external/lit'; +import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api'; +import { MY_GLOBAL_CONTEXT, MyGlobalContextInterface } from '../my-context.context'; + +@customElement('my-custom-dashboard') +export class MyCustomDashboard extends UmbElementMixin(LitElement) { + #myContext?: MyGlobalContextInterface; + + constructor() { + super(); + + // Consume the global context + this.consumeContext(MY_GLOBAL_CONTEXT, (instance) => { + this.#myContext = instance; + }); + } + + async #handleClick() { + if (!this.#myContext) return; + + // Use the context + const user = await this.#myContext.getCurrentUser(); + this.#myContext.setPreference('lastVisit', new Date().toISOString()); + + console.log(`Welcome back, ${user}!`); + } + + render() { + return html` + + Check User + + `; + } } ``` +{% endcode %} From 136fefe3dfe476705967e3cbe190b0f6ee938dda Mon Sep 17 00:00:00 2001 From: Ben Szymanski Date: Thu, 25 Sep 2025 15:34:32 +0200 Subject: [PATCH 3/4] Rewrote global context article to include insights from community meetup, examples of how to create a context and how to consume a context. --- .../extension-types/global-context.md | 156 ++++++++++++++++-- 1 file changed, 145 insertions(+), 11 deletions(-) diff --git a/16/umbraco-cms/customizing/extending-overview/extension-types/global-context.md b/16/umbraco-cms/customizing/extending-overview/extension-types/global-context.md index 744314d195c..89b93a15fcc 100644 --- a/16/umbraco-cms/customizing/extending-overview/extension-types/global-context.md +++ b/16/umbraco-cms/customizing/extending-overview/extension-types/global-context.md @@ -1,24 +1,158 @@ --- -description: Establish the bond for extensions to communication across the application +description: Global contexts in Umbraco provide a clean, type-safe way to share functionality across the backoffice. --- # Global Context -{% hint style="warning" %} -This page is a work in progress and may undergo further revisions, updates, or amendments. The information contained herein is subject to change without notice. -{% endhint %} +The Global Context extension type allows extension authors to create a custom context of data and functions and make it available across the entire backoffice. Unlike other contexts that might be scoped to a specific workspace or view, a global context is available everywhere. These contexts are kept alive through the entire backoffice session. -A global context manages the logic code from your Lit Element controllers. +Consider using a global context when you need to: + +- **Share state across multiple extensions** - Track user preferences or application-wide settings +- **Provide utility functions** - Common operations that multiple parts of an extension +- **Manage centralized services** - API clients, notification handlers, or data repositories +- **Coordinate between different extensions** - Communication layer between dashboards, property editors, and other components +- **Share functionality with other extensions** - Allow other package developers to access features and functionality within the package + +Extension authors should prefer to use other context types [Workspace Contexts](workspaces/workspace-context.md) over Global Contexts. Umbraco itself uses Global Contexts sparingly, for clipboard, current user, and icons. ## Registration of a Global Context -You can register a global context like so: +Global Context extensions can be registered using a manifest file like `umbraco-package.json`. -```typescript +{% code title="umbraco-package.json" %} +```json { - type: 'globalContext', - alias: 'My.GlobalContext.Products', - name: 'My Products Context', - api: 'my-products.context.js', + "$schema": "../../umbraco-package-schema.json", + "name": "My Global Context Package", + "version": "1.0.0", + "extensions": [ + { + "type": "globalContext", + "alias": "My.GlobalContext", + "name": "My Global Context", + "api": "/App_Plugins/my-global-context/dist/my-context.context.js" + } + ] +} +``` +{% endcode %} + +**Key fields:** +- `type`: Must be `"globalContext"`, see: [ManifestGlobalContext](https://apidocs.umbraco.com/v16/ui-api/interfaces/packages_core_extension-registry.ManifestGlobalContext.html) +- `alias`: A unique identifier for the context +- `name`: A human-readable name +- `api`: The path to the compiled JavaScript file + +## Creating Your Global Context + +### 1. Define a Context Token + +First, create a context token. This is how other parts of an extension will reference the context: + +{% code title="src/my-context.ts" %} +```typescript +import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; + +export interface MyGlobalContextInterface { + getCurrentUser(): Promise; + setPreference(key: string, value: any): void; + getPreference(key: string): any; + getHostElement(): Element; +} + +export const MY_GLOBAL_CONTEXT = new UmbContextToken( + 'My.GlobalContext' +); +``` +{% endcode %} + +### 2. Implement the Context Class + +Next, implement the context class: + +{% code title="src/my-context.ts" %} +```typescript +import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; +import { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; + +export class MyGlobalContext extends UmbContextBase implements MyGlobalContextInterface { + #preferences: Map = new Map(); + + constructor(host: UmbControllerHost) { + super(host, MY_GLOBAL_CONTEXT); + } + + async getCurrentUser(): Promise { + // In a real implementation, you'd fetch this from the API + return 'Current User'; + } + + setPreference(key: string, value: any): void { + this.#preferences.set(key, value); + console.log(`Preference set: ${key} = ${value}`); + } + + getPreference(key: string): any { + return this.#preferences.get(key); + } + + getHostElement(): Element { + return this; + } +} + +export default MyGlobalContext; +``` +{% endcode %} + +## Using Global Contexts + +Once the global context extension is registered, it can be consumed in any web component throughout the backoffice. + +{% code title="src/my-custom-dashboard.ts" %} +```typescript +import { + LitElement, + html, + customElement, +} from "@umbraco-cms/backoffice/external/lit"; +import { UmbElementMixin } from "@umbraco-cms/backoffice/element-api"; +import { + MY_GLOBAL_CONTEXT, + MyGlobalContextInterface, +} from "./service-status-context.ts"; + +@customElement("my-custom-dashboard") +export class MyCustomDashboard extends UmbElementMixin(LitElement) { + #myContext?: MyGlobalContextInterface; + + constructor() { + super(); + + // Consume the global context + this.consumeContext(MY_GLOBAL_CONTEXT, (instance) => { + this.#myContext = instance; + }); + } + + async #handleClick() { + if (!this.#myContext) return; + + // Use the context + const user = await this.#myContext.getCurrentUser(); + this.#myContext.setPreference("lastVisit", new Date().toISOString()); + + console.log(`Welcome back, ${user}!`); + } + + render() { + return html` + + Check User + + `; + } } ``` +{% endcode %} From 64f1d4887375f1870fb53ace8862d6696683831b Mon Sep 17 00:00:00 2001 From: Ben Szymanski Date: Tue, 7 Oct 2025 12:17:28 -0500 Subject: [PATCH 4/4] Fixing "generic" issue on context implementation/class --- .../extension-types/global-context.md | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/16/umbraco-cms/customizing/extending-overview/extension-types/global-context.md b/16/umbraco-cms/customizing/extending-overview/extension-types/global-context.md index 89b93a15fcc..84c9bfed6e2 100644 --- a/16/umbraco-cms/customizing/extending-overview/extension-types/global-context.md +++ b/16/umbraco-cms/customizing/extending-overview/extension-types/global-context.md @@ -76,23 +76,26 @@ Next, implement the context class: import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -export class MyGlobalContext extends UmbContextBase implements MyGlobalContextInterface { +export class MyGlobalContext + extends UmbContextBase + implements MyGlobalContextInterface +{ #preferences: Map = new Map(); - + constructor(host: UmbControllerHost) { - super(host, MY_GLOBAL_CONTEXT); + super(host, SERVICE_STATUS_CONTEXT); } - + async getCurrentUser(): Promise { // In a real implementation, you'd fetch this from the API - return 'Current User'; + return "Current User"; } - + setPreference(key: string, value: any): void { this.#preferences.set(key, value); console.log(`Preference set: ${key} = ${value}`); } - + getPreference(key: string): any { return this.#preferences.get(key); }