Early Adopter's Guide to Umbraco v14 Packages : Communicating with the server! - Part 3 - Context
Published: 2024-01-30 23:02:45

_The code for this series of posts can be viewed here : https://github.com/KevinJump/TimeDashboard_

## 4. Context. 
Coming from a Umbraco v13, AngularJs world; Its proribly best to think of the context as the 'service' element - it handles all the code from your controllers (LitElements mostly), does some logic, passes things two and from the repositories and it can do a little state management if you want it to (although maybe thats what the store is for??).

Context's are handled slightly diffrently than repositories and stores, because you want them to have some context for umbraco and the application, which they can then pass on. 

You can instanciate contexts a couple of way's here we are going to make a 'globalContext' simply because we haven't yet talked about workspaces, and elements, and its the simpest to define. 

A global context can be defined like so:

```ts
const contexts : Array<ManifestGlobalContext> = [
    {
        type: 'globalContext',
        alias: 'time.context',
        name: 'Time context',
        js: () => import('./time.context.ts')
    }
]
```
_(we wrap this array into our entry point lower down in our code)_

Our "time context" is a little longer than before but we will step though it. 

### Setup
First we have to get our context setup:

```ts
export class TimeManagementContext extends UmbControllerBase {
   
    #repository: TimeManagementRespository;
   
    constructor(host: UmbControllerHost) {
        super(host);

        this.provideContext(TIME_MANAGEMENT_CONTEXT_TOKEN, this);
        this.#repository = new TimeManagementRespository(this);

        this.consumeContext(UMB_AUTH_CONTEXT, (_auth) => {
            const umbOpenApi = _auth.getOpenApiConfiguration();
            OpenAPI.TOKEN = umbOpenApi.token;
            OpenAPI.BASE = umbOpenApi.base;
            OpenAPI.WITH_CREDENTIALS = umbOpenApi.withCredentials;
        });
    }
```

The key things here, are:

1. **ProvideContext** there are some comments in the core code that you shouldn't self provide the context, but then its done all over the place, and it works. A context must be provided somewhere, with a token, this is how other elements then consume it and all share the context.

2. **Auth Context** : Now this took ages to dig out. 

When you generate your Api (from the openapi cli tool) - the client will generate all the code and config you need to communicate with the sever. **but** it wont have the authentication token.

Umbraco does have this token set for its own config/calls, so we have to go get it and set it on our calls for them to correctly call the server. **miss this step and authentication will not work for you**

> ### 🚨 So to repeat - because its worth repeating 🚨
>
>  make sure you set the OpenAPI values for **your** openAPI 
>  config or authentication will seem to be a mystery to you.
>
> ```
> this.consumeContext(UMB_AUTH_CONTEXT, (_auth) => {
>    const umbOpenApi = _auth.getOpenApiConfiguration();
>    OpenAPI.TOKEN = umbOpenApi.token;
>    OpenAPI.BASE = umbOpenApi.base;
>    OpenAPI.WITH_CREDENTIALS = umbOpenApi.withCredentials;
> });
> ```

### properties 
Now we are going to give out context some properties, and introduce 'observables' which are just things you can watch for changes.

```ts
#time = new UmbStringState("unknown");
public readonly time = this.#time.asObservable();

#date = new UmbStringState("unknown");
public readonly date = this.#date.asObservable();
```

### methods 

Here we are going to set the methods, these are very close to being the things we are going to call when someone clicks something!.

These methods call the repository (which calls the store, which calls the resources, which calls the serever). and returns the data. 

```ts
async getTime() {
    const {data} = await this.#repository.getTime();

    if (data) {
        this.#time.setValue(data);
    }
}

async getDate() {
    const {data} = await this.#repository.getDate();

    if (data) {
        this.#date.setValue(data);
    }
}
```

### Export and define 

Finally we export and define out context. 

```ts
export default TimeManagementContext;

export const TIME_MANAGEMENT_CONTEXT_TOKEN =
    new UmbContextToken<TimeManagementContext>
            (TimeManagementContext.name);
```

The token is important in other elements finding your context;

Exporting it as default means you can do the `js: ()=> import` line in the manifest, and when all the code is bundles references are included. 

Next . A Button !!!

---

> _**Updated**: 2/3/2024: preview008. UmbBaseController -> UmbControllerBase_