Create, register and use shortcodes in WordPress
18/03/2023Learn how to create and register your own WordPress shortcodes to add dynamic content to your posts and pages.
I’ve been building custom element web components in JavaScript for several months now (modal, tabs, menu, sidebars, inputs, context menus, etc) and I see them as the perfect accompaniment or replacement for front-end frameworks. I thought I would write a tutorial series because I often find myself explaining to other developers what web components are.
There are already frameworks, like litElement, for helping build web components. Personally I prefer vanilla JavaScript code so I will be showing you how to make vanilla web components. As a result, when we come to polyfill we will have to take some extra care.
In this series we will start with a bit of theory and move on to implementing what we know by building a modal dialogue box. A modal is a good example to use because we will have to learn how to use a slotted shadow root, lifecycle callbacks and advanced CSS styling selectors.
A web component is basically a cocktail consisting of a Custom Element, a Shadow DOM and a HTML Template. They allow JavaScript developers to define their own HTML elements, complete with encapsulated custom behaviours, logic, structure and styles.
Within your document they look like normal HTML tags (conventionally with a hyphen) with functionality you would normally find in more complicated HTML, CSS and JavaScript structures.
<div>
<p>An example of what a web component tag might look like in context</p>
<button onClick="openModal()">Open</button>
<gb-modal>
<p>Modal content</p>
</gb-modal>
</div>
Web components are supported by all major browsers and can be polyfilled for Edge. Internet Explorer does have a myriad of issues with them, but screw internet explorer, right?
So what is a Custom Element, Shadow DOM and HTML Template?
Simply, this is a collection of JavaScript APIs which allow developers to make their own fully-featured DOM elements. They look something like this:
<gb-component></gb-component>
Rendered separately to your main DOM, a Shadow DOM is an encapsulated element tree. Think of it a bit like a document fragment where elements, behaviours and styles are abstracted away from your main document, keeping them private – fancy scoping, if you prefer.
The light DOM is the content inside your main document.
I imagine everyone has come across HTML Templates. They allow developers to make ‘render-when-needed’, reusable, slotted templates to be scattered like confetti once instantiated by JavaScript.
Encapsulated, clean and reusable code. As the web has evolved, complex GUI and applications have become trickier and trickier to maintain cleanly. By building web components we can abstract our code and structure into custom HTML elements, neatly called from their own HTML tags.
I can make a web component which can be dropped into any application without the application screwing with my web component or my web component screwing with the application. Great, right?
Let’s look at the basic structure of a web component; a JavaScript class which extends HTMLElement:
class ClassName extends HTMLElement {
constructor() {
super();
if (!this.shadowRoot) {
this.attachShadow({mode: 'open'});
this.shadowRoot.innerHTML = ``;
}
}
connectedCallback() {
}
static get observedAttributes() {
return [];
}
attributeChangedCallback(name, oldValue, newValue) {
}
disconnectedCallback() {
}
}
customElements.define('element-name', ClassName);
The shadowRoot is where we attach the HTML Template. Access to the Light DOM can be given through slot tags, but ‘most’ of the structure we place inside the shadowRoot is protected within the Shadow DOM.
A typical shadowRoot could look like this:
if (!this.shadowRoot) {
this.attachShadow({mode: 'open'});
this.shadowRoot.innerHTML = `
<style>
.inner {
background-color: green;
}
</style>
<div class="inner">
<slot></slot>
</div>
`;
}
In this example, a common CSS class (‘inner’) is unique inside the shadowRoot, even if used in our main document style sheet. The main document styling does not penetrate the Shadow DOM and the styling inside the shadowRoot does not leak to the main document.
A web component contains several lifecycle callbacks. These are functions inside the web component which are invoked under certain conditions, such as when an attribute is updated or the component is connected.
The connectedCallback allows us to modify behaviour when a web component is first connected to the DOM. This is useful because it gives us a place to hook up actions such as event listeners.
The opposite of the connected callback, the disconnected callback is invoked when the web component is removed from the DOM. Therefore we can do useful things, like remove event listeners, when we no longer need our component.
The attributeChangedCallback is a mutation observer watching for changes on the attributes of a web component. This is useful because we can change attribute values to trigger custom behaviours.
Check back in a few days for the next Web Components tutorial and to learn about HTML Templates in Web Components.
Learn how to create and register your own WordPress shortcodes to add dynamic content to your posts and pages.
Learn how to improve code readability and performance by using guard clauses in JavaScript. Discover their benefits and best practices.
Learn the difference between implements and extends in TypeScript. Use Implements to implement interfaces and types, and extends to inherit from classes.
In this tutorial we will look at using YAML in PHP. Learn about Parsing and Writing YAML files using Symfony's YAML component.
Measuring code execution performance is an important way to identify bottlenecks. Use these methods in JavaScript to help optimise your code.
Find bottlenecks, optimise and clean your code, and speed up your apps by measuring the execution time of your PHP scripts using microtime.
Learn how to regenerate and update WordPress media and image sizes both programmatically (without plugin), and also with a handy plugin.
Ever seen constants like __DIR__ and __FILE__ being used in PHP? These are 'Magic Constants', and this is how we can use them.
Learn how to use event listeners to detect and handle single and multiple keypress events in JavaScript. Add modifier keys to your application!