As a best practice, Akita recommends separating the Domain State from the UI State. Domain State is the state of your application in the server side, while the UI state is information that’s relevant to the UI alone, and therefore not stored in the server. Some examples of that are the current time based on the user’s machine, which tab is the active one, or whether a drop-down is open.

Let’s examine two types of UI states by looking at real-world examples from our application, and how we manage them with Akita:

Global UI State

Here we have a page where we display a list of widgets. Each widget shows the user’s data differently, depending on what the user has selected. It can be a bar chart, a pie, a simple list, etc.

At the top of the page, there’s a date picker component responsible for filtering the widgets` data.

First, we know that we need to maintain a collection of widgets so we’ll create an EntityStore :

In addition to the widget entities, we know that we need to maintain the user’s selected date. This date is applied globally to all widgets, rather than per widget, so the best place to store it is on the store root state:

We can extend our entity store and add more properties to it. In our case, we’ve added the date, and set the default value to be the current date.

As you can see, we put the date under a ui key, to make it clear that the values it holds belong to a UI state.

At this point, our store state looks like the following:

A screenshot from redux dev-tools

We have the default properties that comes with EntityStore and our extended ui object.

Now, we can use the store’s update() method to update the date property and the query’s select() method to get the date reactively:

When we have multiple UI properties in the store, it’s recommended to create a helper updateUI() method, for example:

Entity UI State

There are times when we need to have an entity-based UI state. For example, if we need to know various ui-related data on the current entity — whether it is open, loading, etc.

There are two reasons we’d want to have this separation of concerns:

We don’t want to interfere with the entity that we get from the server, because otherwise we’ll need to clean up what we added when sending it back, to avoid sending a redundant payload over the network.

If we keep the data in the entity and don’t clean it up, it can end up as part of the entity’s database entry (since it’s not uncommon in databases to allow for free-formed JSON data fields to be stored). In this scenario we might end up with a lot of of garbage in our database.

Active Entity Management

Continuing with the example from our application, when a user selects a widget, we need to open a sidebar panel and display its settings within it:

Luckily, Akita comes with built-in support for an active attribute, used to hold the active entity’s id, which make managing the active entity a breeze.

Akita supports both single and multiple active entity management. In our case we need to maintain one active entity, so we need to extend the ActiveState interface to our store:

Now we can use the API that Akita provides to update and query the active entity, for example:

And here’s how we can use that API in our example:

Managing More Complex UI Entity States

So far so good, but there are times when we need more than that. In our example application, each widget entity requires managing a lot more UI state properties (for instance: whether the widget is interactive, if its data is cached, what mode it’s in etc.).

For cases like these, Akita provides a built-in UI store and an accompanying UI query, which you can create on demand.

The only thing we need to do is to add the ui property, passing the entity UI interface, and then call the createUIStore() in the entity store’s constructor and createUIQuery() in the entity query’s constructor.

With this setup, Akita will instantiate a new EntityStore and EntityQuery under the ui property, which will be responsible for managing the entity UI state.

Now, when we want to update a property in our UI store, we can call any store method we want, for example:

And observe every change in the Redux dev-tools:

Hot update: Initial UI Entity State

Today, we’ve added new functionality based on a feature request that was submitted yesterday. Starting from v3.2, it’s possible to pass an initial entity state in the UI store:

With this setup, each time we create a new entity for the encompassing entity store, by calling the set() or add() methods, Akita automatically generates an accompanying UI entity for this entity with the values we specified. In addition, whenever we remove the related entity from the model, Akita automatically removes the UI entity associated with it.

Querying a UI Entity

There are several ways to query a UI entity. The first option is to create a method in the component:

Note that we employ memoization because we don’t want to return a new observable upon each change detection (this functionality isn’t specific to Akita, it’s how Angular CD works).

The second option is to create a dedicated component or directive, pass the id as input, and query the required part from the UI entity:

This way we’ll have one instance per entity and we can keep our component compact.

Last but not least, we can create a derived query method that merges both the model and the UI, by using the combineLatest operator:

When using this option, consider including the auditTime operator. You can find a detailed explanation for why you might need it in the following article:

We’re Hiring

We’re looking for great front-end developers. If you’re one of them, you’re passionate about technology, and you want to work for the best company in the world, come and join me.

Additional Resources