Web Component Lifecycle
A mathfield web component goes through various stages during its lifecycle.
In most cases, this is something you don’t have to pay much attention to. Just remember these guidelines:
- Once a component is attached to the DOM, attributes (key/value pairs
attached to the
<math-field>
tag and properties (key/value pairs attached to aMathfieldElement
object) are kept in sync, or reflected, except for thevalue
attribute which only reflect the inital value, not the current one. You can also call the functions ofMathfieldElement
without limitations. - To be notified when the component is attached to the DOM, listen for a
mount
event on the element. - Before the component is attached to the DOM or even before the
MathfieldElement
class has been registered, you can interact with the element, but with some limitations. Thevalue
,selection
,options
,disabled
properties and the properties matching an attribute (readOnly
forread-only
, etc…) and related attributes are safe to set, but the values you read back may be different once the component is mounted.
① Before Initialization
When the page is loaded, before any code is loaded or executed, elements with a
<math-field>
tag will be laid out and rendered by the browser as if they were
a <div>
.
To prevent this from happening, you can use the not(:defined)
CSS
selector and set the display
CSS property to none
. This will prevent
some potentially undesirable flash of content when the page is loaded.
math-field:not(:defined) {
display: none;
}
You can take some additional steps to ensure an optimal loading experience with minimal layout shifts.
② Initialization
The element has been created from markup, but the code registering
the <math-field>
tag with the MathfieldElement
class has not been executed
yet. This could happen if the scripts are loaded in an unexpected order or
if there is a temporary networking issue.
At this stage:
- you can read and change the
disabled
,value
,options
,selection
andposition
properties on the element.
document.querySelector('math-field').value = '\\sin x';
However, some of those properties behave in a limited way.
- you can change/add/remove attributes on the element. At this stage, the
attributes and the properties are independent, so if you set for example the
math-virtual-keyboard-policy
attribute, it will not be reflected inmf.mathVirtualKeyboardPolicy
. - the only methods on the element that can be invoked are those of
HTMLElement
since the element has not been upgraded yet.
To be notified when the registration takes place, use customElements.whenDefined()
.
You may want to wait for this to access and modify some global properties
of MathfieldElement
customElements.whenDefined('math-field').then(() => {
MathfieldElement.fontsDirectory = "assets/fonts/";
});
If all goes well, the element will be constructed next.
③ Constructed
This stage occurs either after the previous one (i.e. an element created
from markup) or when an element is created programmatically with new MathfieldElement()
.
The HTMLElement
object exist, but it is not yet attached to the DOM. You can
interact with the element, but its operations are still limited.
At this stage:
- you can read and change the properties as before. However, doing so will
be reflected on attributes as well. That is calling
mf.mathVirtualKeyboardPolicy = "manual"
will result inmf.getAttribute('math-virtual-keyboard-policy')
to return"manual"
. - you can read and change the attributes as before, however they will now
be reflected on properties as well, that is calling
mf.setAttribute('math-virtual-keyboard-policy', 'manual')
will result in the value ofmf.mathVirtualKeyboardPolicy
to be"manual"
. - you can change/add/remove attributes on the element
- you can invoke all methods specific to
MathfieldElement
, however some may have some limitations. For examplesetValue()
will ignore any options provided including formats other than LaTeX,executeCommand()
will do anything, etc… These commands require the element to be attached to the DOM to function properly. But no worries, that’s what happens next.
④ Attached/Mounted
This stage normally occurs after the element has been constructed.
The transition to this stage happens automatically for elements created from
markup after the MathfieldElement
class has been registered to handle the
<math-field>
tag.
If the element was created programatically, this stage is reached when the
element is explicitly attached to the DOM, for example using appendChild()
.
At this stage:
- you can read and change properties and attributes and they will reflect each other (changing an attribute will update the corresponding property and vice versa).
- you can invoke all functions of
MathfieldElement
without limitations
To be notified when this stage is reached, listen for the mount
event on
the element:
md.addEventListener('mount', (ev) => {
console.log('mf is mounted');
// You can now read default options value for example, or
// call `setValue()` with format options other than LaTeX.
console.log(ev.target.macros);
});
⑤ Detached/Unmounted
This stage can be reached if the element is explicitly removed from the DOM,
for example with ChildNode.remove()
.
This stage is not reached when the page is closed: in that case the element is immediately disposed of.
Once this stage is reached, the same limitations as in the Constructed stage apply.
Note that the next stage could be either for element to be disposed of or to be re-attached.
To be notified when this stage is reached, listen for the unmount
event on
the element:
md.addEventListener('unmount')((ev) => {
console.log('mf is about to be unmounted');
// Last chance to interact with the mathfield
console.log(ev.target.getValue('ascii-math'));
});