Constructor
new BaseCustomElement()
- Source:
Example
// Replaces all span elements inside the component with
// an upper-cased value of the attribute 'some-attribute'
class MyComponent extends BaseCustomElement {
static tagName = "my-component"
static observedAttributes = [
"show-warnings",
"some-attribute",
]
someAttributeChangedCallback({newValue}) {
this.someAttribute = newValue ? newValue.toUpperCase() : null
}
update() {
const spans = this.querySelectorAll("span")
if (spans.length == 0) {
this.logger.warn("Did not find any <span> elements - element won't do anything")
}
spans.forEach( (element) => {
element.textContent = this.someAttribute
})
}
}
docment.addEventListener("DOMContentLoaded", () => {
MyComponent.define()
})
// Then, in your HTML
<my-component some-attribute="hello there">
<span></span>
<div></div>
<span></span>
</my-component>
// The browser will effectively produce this HTML:
<my-component some-attribute="hello there">
<span>HELLO THERE</span>
<div></div>
<span>HELLO THERE</span>
</my-component>
// If JavaScript (or browser dev tools) changed some-attribute
// to be "goodbye then", the markup will change to look like so:
<my-component some-attribute="goodby then">
<span>GOODBYE THEN</span>
<div></div>
<span>GOODBYE THEN</span>
</my-component>
Members
connectedCallbackCalled
Returns true if this element is connected and the connected callback has been called.
This is different from Node#isConnected
, which can return true before connectedCallback
is called.
- Source:
logger
A Logger
you can use to write warning messages. By default, these
messages are not shown in the console. If you put show-warnings
as an attribute on your
element, warnings sent to this logger are shown.
- Source:
Methods
attributeChangedCallback()
Overrides the standard callback to allow subclasses to have a slightly easier API when responding
to attribute changes. You can override this to use the custom element callback directly. Note that if
you do, show-warnings
will not have any affect and you probably don't need to bother using
this class as your base class.
This method will locate a per-attribute method and call that.
Attribute names are assumed to be in kebab-case and are translated to camelCase to create a method name.
That method is «attributeInCamelCase»ChangedCallback
, so if your attribute is hex-code
,
a method named hexCodeChangedCallback
in invoked. If no such method is defined, a
warning is logged in the console, regardless of the show-warnings
attribute.
The method is invoked with {oldValue,newValue,newValueAsBoolean}
- i.e. an object and not positional parameters. This
means your implementation can omit any parameters it doesn't care about. newValueAsBoolean
is not part of
the custom element spec, but is provided as an unambiguous way to know if a boolean attribute was set or not. This is
because if the value is set, it is likely to be the empty string, which is considered false by JavaScript. Cool.
The return value of the method is ignored.
After your method is called, if there is a method named update
, it is called with no arguments.
What this allows you to do is separate how you manage your element's attributes from how your logic is managed. For complex elements that take a lot of attributes, this can simplify your element's code without straying too far from the spec.
- Source:
- See:
Example
// If your element accepts the attribute `warning-message` that will be trimmed of whitespace
// then placed into all `H1` tags inside the element, you can manage that like so:
class MyElement extends BaseCustomElement {
static tagName = "my-element"
static observedAttributes = [
"warning-message",
]
// called by attributeChangedCallback when warning-message's value changes
warningMessageChangedCallback({newValue}) {
this.warningMessage = (newValue || "").trim()
}
// called after attributeChangedCallback calls warningMessageChangedCallback
update() {
this.querySelectorAll("h1").forEach( (e) => e.textContent = this.warningMessage )
}
}
connectedCallback()
Overrides the custom element callback to set internal flags allowing you to know if your
element has been connected. update
is still called for elements that have not yet connected, however
in practice your element will be connected before any codepath that calls update
is called.
To add logic when your element is connected, override onConnected
- Source:
- See:
disconnectedCallback()
Overrides the custom element callback to set internal flags allowing you to know if your
element has been disconnected. When an element is disconnected, update
is not called.
If you want to add your own logic during disconnection, override onDisconnected
.
- Source:
- See:
onConnected()
Override this to add logic when connectedCallback
is called by the browser. This will
not be called if you overrode connectedCallback
- Source:
onDisconnected()
Override this to add logic when disconnectedCallback
is called by the browser. This will
not be called if you overrode disconnectedCallback
.
- Source:
update()
Override this to perform whatever logic your element must perform. Because changes to your element's attributes can happen at any time and in any order, you will want to consolidate all logic into one method—this one. You will also want to make sure that this method is idempotent and fault-tolerant. It will be called multiple times.
It is called by attributeChangedCallback
and connectedCallback
, however
it will not be called after the elment has been disconnected.
That means that any event listeners, rendering, content manipulation, or other behavior should happen hear and it must be idempotent. In particular, any event listeners you attach must be done with care. Using anonymous functions could result in duplicate listeners.
- Source:
(static) define()
You must call this to define the custom element. This is bascially
a wrapper around customElements.define
. It is recommended that you call
this inside a DOMContentLoaded
event, or after the page's HTML has been processed.
- Source:
- See: