Skip to content

Commit 58f0eb2

Browse files
committed
Added Niels changes from GitBook
1 parent 4615df2 commit 58f0eb2

File tree

2 files changed

+40
-124
lines changed

2 files changed

+40
-124
lines changed
Lines changed: 30 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,20 @@
11
---
22
description: >-
3-
Learn how to create workspace contexts that manage shared state and enable communication between extensions in a workspace.
3+
Workspace Contexts manages shared state and enables communication between extensions in a workspace.
44
---
55

66
# Workspace Context
77

8-
Workspace Contexts serve as the central communication hub for workspace extensions, providing shared state management within workspace boundaries. They enable different workspace components to interact through a common data layer.
8+
Workspace Contexts serve as the central communication hub for workspace extensions, providing shared state management within the boundaries of the Workspace. They enable different Workspace components to interact through a common data layer.
99

1010
## Purpose
1111

1212
Workspace Contexts provide:
1313

14-
- **Shared state** scoped to a specific workspace instance
15-
- **Communication layer** between extensions in the workspace
16-
- **Entity lifecycle management** for workspace data
17-
- **Context isolation** ensures workspace independence
18-
19-
{% hint style="info" %}
20-
Workspace Contexts are automatically scoped to their workspace. Extensions in different workspaces cannot access each other's contexts.
21-
{% endhint %}
14+
- **Shared state** scoped to a specific workspace instance.
15+
- **Communication layer** between extensions in the workspace.
16+
- **Entity lifecycle management** for workspace data.
17+
- **Context isolation** ensures workspace independence.
2218

2319
## Manifest
2420

@@ -39,7 +35,7 @@ Workspace Contexts are automatically scoped to their workspace. Extensions in di
3935
```
4036
{% endcode %}
4137

42-
## Implementation
38+
## API Implementation
4339

4440
Create a workspace context by extending `UmbContextBase` and providing a unique context token. Add this to your project to enable shared state management between workspace extensions:
4541

@@ -50,7 +46,7 @@ import { UmbContextBase } from '@umbraco-cms/backoffice/class-api';
5046
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
5147
import { UmbNumberState } from '@umbraco-cms/backoffice/observable-api';
5248

53-
export class WorkspaceContextCounterElement extends UmbContextBase {
49+
export class WorkspaceContextCounter extends UmbContextBase {
5450
#counter = new UmbNumberState(0);
5551
readonly counter = this.#counter.asObservable();
5652

@@ -67,139 +63,55 @@ export class WorkspaceContextCounterElement extends UmbContextBase {
6763
}
6864
}
6965

70-
export const api = WorkspaceContextCounterElement;
71-
72-
export const EXAMPLE_COUNTER_CONTEXT = new UmbContextToken<WorkspaceContextCounterElement>(
73-
'UmbWorkspaceContext',
74-
'example.workspaceContext.counter',
75-
);
66+
export const api = WorkspaceContextCounter;
7667
```
7768
{% endcode %}
7869

79-
## Context Token Pattern
70+
## Context Token
8071

81-
Always use `'UmbWorkspaceContext'` as the first parameter in your context token to ensure proper workspace scoping and isolation:
72+
A Context Token is used to consume or get a Context. Read more about [Context Consumption here](../../../foundation/context-api/consume-a-context.md).
8273

8374
```typescript
84-
export const MY_WORKSPACE_CONTEXT = new UmbContextToken<MyWorkspaceContext>(
75+
export const EXAMPLE_COUNTER_CONTEXT = new UmbContextToken<WorkspaceContextCounter>(
8576
'UmbWorkspaceContext', // Ensures workspace scoping
86-
'my.extension.alias', // Must match manifest alias
77+
'example.workspaceContext.counter', // Must match manifest alias
8778
);
8879
```
8980

90-
## Workspace Lifecycle
91-
92-
### Initialization
93-
94-
- Created when workspace loads
95-
- Available to all extensions within that workspace
96-
- Destroyed when workspace closes
97-
98-
### Scoping
99-
100-
- Context instances are isolated per workspace
101-
- Extensions can only access contexts from their own workspace
102-
- Context requests automatically scope to the nearest workspace
103-
104-
### Conditions
105-
106-
Workspace contexts only initialize when their conditions match:
107-
108-
```typescript
109-
conditions: [
110-
{
111-
alias: UMB_WORKSPACE_CONDITION_ALIAS,
112-
match: 'Umb.Workspace.Document', // Only available in document workspaces
113-
},
114-
],
115-
```
116-
117-
## Entity Data Patterns
81+
When declaring a Workspace Context, always use `'UmbWorkspaceContext'` as the first parameter in your Context Token to ensure proper context isolation.
11882

119-
### Draft State Management
83+
## Extension Communication
12084

121-
```typescript
122-
export class EntityWorkspaceContext extends UmbContextBase {
123-
#entity = new UmbObjectState<MyEntity | null>(null);
124-
#isDirty = new UmbBooleanState(false);
125-
126-
readonly entity = this.#entity.asObservable();
127-
readonly isDirty = this.#isDirty.asObservable();
128-
129-
updateEntity(changes: Partial<MyEntity>) {
130-
const current = this.#entity.getValue();
131-
if (current) {
132-
this.#entity.setValue({ ...current, ...changes });
133-
this.#isDirty.setValue(true);
134-
}
135-
}
136-
}
137-
```
85+
### Workspace Action
13886

139-
### Server Integration
87+
The following example shows how to call the increment method from a Workspace Action API.
14088

14189
```typescript
142-
export class ServerEntityContext extends UmbContextBase {
143-
#repository = inject(MyEntityRepository);
144-
145-
async save() {
146-
const entity = this.#entity.getValue();
147-
const saved = await this.#repository.save(entity);
148-
this.#entity.setValue(saved);
149-
this.#isDirty.setValue(false);
90+
export class MyIncreaseCounterWorkspaceAction extends UmbWorkspaceActionBase {
91+
override async execute() {
92+
const context = await this.getContext(EXAMPLE_COUNTER_CONTEXT);
93+
context.increment();
15094
}
15195
}
15296
```
15397

154-
## Extension Communication
98+
### Workspace View
15599

156-
### In Workspace Actions
100+
The following example shows how a Workspace View Element can consume a context.
157101

158102
```typescript
159-
export class MyWorkspaceAction extends UmbWorkspaceActionBase {
160-
override async execute() {
161-
const context = await this.getContext(MY_WORKSPACE_CONTEXT);
162-
context.performAction();
163-
}
164-
}
165-
```
103+
export class MyWorkspaceView extends UmbElementMixin(LitElement) {
166104

167-
### In Workspace Views
105+
@state()
106+
_count?: number;
168107

169-
```typescript
170-
export class MyWorkspaceView extends UmbElementMixin(LitElement) {
171108
constructor() {
172109
super();
173-
this.consumeContext(MY_WORKSPACE_CONTEXT, (context) => {
174-
this.observe(context.data, (data) => this.requestUpdate());
110+
this.consumeContext(EXAMPLE_COUNTER_CONTEXT, (context) => {
111+
this.observe(context.counter, (count) => this._count = count);
175112
});
176113
}
114+
115+
// A render using _count
177116
}
178117
```
179-
180-
## Best Practices
181-
182-
### State Encapsulation
183-
184-
```typescript
185-
// ✅ Private state with public observables
186-
#data = new UmbObjectState(initialData);
187-
readonly data = this.#data.asObservable();
188-
189-
// ❌ Direct state exposure
190-
data = new UmbObjectState(initialData);
191-
```
192-
193-
### Context Token Consistency
194-
195-
```typescript
196-
// ✅ Use workspace scoping
197-
new UmbContextToken<T>('UmbWorkspaceContext', 'my.alias');
198-
199-
// ❌ Generic context (not workspace-scoped)
200-
new UmbContextToken<T>('MyContext', 'my.alias');
201-
```
202-
203-
### Conditional Availability
204-
205-
Only provide contexts when they are meaningful for the workspace type.

17/umbraco-cms/customizing/foundation/states.md

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
11
---
22
description: >-
33
Make reactivity with Umbraco States, enabling you to provide a value that
4-
multiple others can observe and thereby be updated when the value changes.
4+
others can observe and thereby be updated when the value changes.
55
---
66

77
# States
88

9-
An Umbraco State is a container for a value, it enables you to create [Observables](states.md#observables), which is the name of a hook into the States value — An Observable can then be Observed, such observation provides the current value and if the value of the State changes they will all be updated accordingly.
10-
11-
A typical use case is when you need to implement reactivity across class instances. For example, a State is in a Context and the Observer is a Element. For a concrete example, see the [Extension Type Workspace Context](../extending-overview/extension-types/workspaces/workspace-context.md) article.
12-
139
{% hint style="info" %}
14-
Umbraco States are not relevant when dealing with the reactivity of a Web Component. For that, see the [Lit Element](lit-element.md) article.
10+
Umbraco States are not relevant when dealing with the reactivity of a Web Component. For more information, see the [Lit Element](lit-element.md) article.
1511
{% endhint %}
1612

13+
An Umbraco State is a container for a value. You create [Observables](../foundation/states.md#observe), which is the name of a hook into the State's value. An Observable can then be observed, providing the current value, and if the value of the State changes, all Observables will be updated accordingly.
14+
15+
A typical use case is to bring reactivity across class instances. For example, a Context may provide a value that an Element needs to utilize.
16+
17+
In this case, the Context would implement a State and an Observable of it. The Element would then observe the Observable of the Context.
18+
19+
You can see an example of this pattern in the [Extension Type Workspace Context](../extending-overview/extension-types/workspaces/workspace-context.md) article.
20+
1721
The example below demonstrates the basics of working with a State and observing its changes:
1822

1923
```

0 commit comments

Comments
 (0)