At HAXeditor and HAXsite core data storage is MobX. MobX provides simple, scalable state management and the two data stores work together to provide individual yet integrated capability. MobX is how all pieces of the application understand what is 'active' either at the editor or site layer. It's how the editor can operate without the site and the site can understand the editor to help create a decoupled yet seamless experience.
Store properties
This list may fall out of date, however the store is not commonly modified, when it is, it is api enhancement as opposed to removal. HAXsite's MobX store is simple and primarily in charge of bridging the router (url slug / path) with what the 'activeId' is. From there, the activeItem from the site.json manifest's items array can be correctly identified.
Each property is listed and available on the store. To pull in the store in your code write the following:
import { store } from "@haxtheweb/haxcms-elements/lib/core/haxcms-site-store.js";
import { autorun, toJS } from "mobx";
MobX store props
{
location: observable.ref, // router location in url
currentRouterLocation: observable.ref,
internalRoutes: observable, // internal routes to haxcms
editMode: observable, // global editing state
jwt: observable, // json web token
userData: observable, // user data object for logged in users
manifest: observable, // JOS / manifest
activeItemContent: observable, // active site content, cleaned up
themeElement: observable, // theme element
version: observable, // version of haxcms FRONTEND as per package.json
routerManifest: computed, // router mixed in manifest w/ routes / paths
siteTitle: computed, // site title
siteDescription: computed, // site description
isLoggedIn: computed, // simple boolean for state so we can style based on logged in
themeData: computed, // get the active theme from manifest + activeId
regionData: computed, // get the active region data from manifest + activeId
entityData: computed, // get entity data from manifest
homeLink: computed,
activeId: observable, // this affects all state changes associated to activeItem
activeItem: computed, // active item object
activeItemFields: computed, // active item field values
activeManifestIndex: computed, // active array index, used for pagination
activeManifestIndexCounter: computed, // active array index counter, used for pagination
activeTitle: computed, // active page title
activeTags: computed, // active page tags
parentTitle: computed, // active page parent title
ancestorTitle: computed, // active page ancestor title
ancestorItem: computed, // active page ancestor
darkMode: observable, // dark mode pref
soundStatus: observable, // toggle sounds on and off
appReady: observable, // system is ready via firstUpdated of haxcms-site-builder
badDevice: observable, // if we have a low performance device
pageAllowed: observable, // if the page operations are allowed to be viewed
}
MobX common usage
You create a LitElement which is stateful and reactive to properties
You want to subscribe to this style of property reactivity when changes happen in HAXsite or HAXeditor
toJS / autorun paradigm
While MobX has extensive docs, this is the most common way that you can integrate with HAX in the ways most people will care about. The following is how site-title knows to render the title, react to being in an editable state, and change when the manifest updates the name of the site.
site-title and many other blocks are available for theme development.
The most common way to get notified to changes in the store is with autoruns. A full example is below as Core development approach, however here's the critical piece.
Here's how you can read and interpret the above (which can be applied to ANY store property):
Automatically run the following code whenever siteTitle changes in the store
This is part of the magic of MobX! It does textual analysis to say "the store cares about siteTitle so rerun this anonymous function because the code says it cares about siteTitle"
toJS clones the siteTitle so that it is a stand alone string as opposed to a Proxy object (the thing making MobX so powerful under the hood)
in your LitElement / web component then you'd react to changes in this.siteTitle, render and respond as you see fit!
the this.__disposer block is referenced below and is just data clean up in the event this element is not persistently rendered in the page.
Check understanding
Scroll back up the page, any property that we add to the MobX store you can subscribe to changes with the approach mentioned!
You are one step closer to unlocking the magic of MobX + HAX!
Core development approach to site-title
/**
* Copyright 2019 The Pennsylvania State University
* @license Apache-2.0, see License.md for full text.
*/
import { LitElement, html, css } from "lit";
import { store } from "@haxtheweb/haxcms-elements/lib/core/haxcms-site-store.js";
import { autorun, toJS } from "mobx";
import { HAXCMSI18NMixin } from "../../core/utils/HAXCMSI18NMixin.js";
import "@haxtheweb/simple-icon/lib/simple-icon-lite.js";
import "@haxtheweb/simple-icon/lib/simple-icons.js";
import { HAXCMSThemeParts } from "@haxtheweb/haxcms-elements/lib/core/utils/HAXCMSThemeParts.js";
/**
* `site-title`
* `Title of the site`
*
* @demo demo/index.html
*/
class SiteTitle extends HAXCMSThemeParts(HAXCMSI18NMixin(LitElement)) {
/**
* LitElement constructable styles enhancement
*/
static get styles() {
return [
super.styles,
css`
:host {
display: block;
text-rendering: optimizelegibility;
position: relative;
color: inherit;
--simple-icon-width: 32px;
--simple-icon-height: 32px;
}
a {
color: inherit;
display: var(--site-title-link-display, block);
text-decoration: var(--site-title-link-text-decoration);
}
simple-icon-lite {
margin-right: 8px;
}
a h1 {
display: var(--site-title-link-h1-display, block);
color: inherit;
text-rendering: optimizelegibility;
font-family: var(--site-title-heading-font-family);
font-size: var(--site-title-heading-font-size);
margin: var(--site-title-heading-margin);
padding: var(--site-title-heading-padding);
text-align: var(--site-title-heading-text-align);
text-rendering: var(--site-title-heading-text-rendering);
font-weight: var(--site-title-heading-font-weight);
line-height: var(--site-title-heading-font-size);
}
`,
];
}
/**
* Store the tag name to make it easier to obtain directly.
*/
static get tag() {
return "site-title";
}
constructor() {
super();
this.HAXCMSI18NMixinBase = "../../../";
this.__disposer = [];
this.icon = null;
this.t = {
home: "Home",
};
this.notitle = false;
autorun((reaction) => {
this.siteTitle = toJS(store.siteTitle);
this.__disposer.push(reaction);
});
autorun((reaction) => {
this.homeLink = toJS(store.homeLink);
this.__disposer.push(reaction);
});
autorun((reaction) => {
this.editMode = toJS(store.editMode);
this.__disposer.push(reaction);
});
}
_editClick(e) {
if (this.disabled || this.editMode) {
e.preventDefault();
}
}
/**
* LitElement
*/
render() {
return html`
${this.notitle ? `` : html`