The Web Component APIs in JavaScript are great, but they're relatively new and kinda hard to learn. They're also struggling to gain traction in the industry still (at the time of writing), making them a little risky to invest in. In the meantime, there are simple patterns you can follow to make components in vanilla JavaScript without the Web Component APIs.
First, let's establish a more declarative way to create a DOM node. You can use a library like jQuery, or define a function to do it yourself. In this article let's use our own function called $
.
// Return a DOM element created from parsing the HTML string
function $(html, properties = {}) {
const template = document.createElement("template");
template.innerHTML = html.trim();
const element = template.content.firstChild;
// Copy the properties to the element
Object.assign(element, properties);
return element;
}
Usage:
const form = $(`<form></form>`);
Now let's make a little component. Let's say we want a generic CRUD form component...
function newCrudForm(data, mode) {
const form = $(`<form></form>`);
render(mode);
function render(mode) {
form.innerHTML = "";
const disabledInRead = mode == "read" ? "disabled" : "";
form.append(
$(`<label>Text: </label>`),
$(`<input type="text" ${disabledInRead} />`, {
value: data.text,
// NOTE: Using this method syntax will bind 'this' to the textbox
oninput() {
data.text = this.value;
},
}),
$(`<button>${mode == "read" ? "Edit" : "Save"}</button>`, {
onclick() {
const newMode = mode == "read" ? "update" : "read";
render(newMode);
},
})
);
}
return form;
}
Note: For simplicity, I didn't implement two-way binding, but it can be added to $
easily
Usage:
const data = { text: "example text" };
document.body.append(newCrudForm(data, "read"));
Explanation
newCrudForm
returns a form element with its own "state". Its state consists of the data
object and the mode
string. The data
state is bound to the textbox. To change the mode
state and react to the change, we just need to re-render and pass in a new value. That's what the button does.
Note: "state" is just the info associated with a component
Conclusion
Hopefully you'll find this easier to learn than the Web Component APIs like I did. Thoughts? Questions? Criticism? Leave a comment below 👇
Top comments (2)
You have created a fancy DOM element, but this is not a Web Component created with the Custom Elements API
Thanks for the comment. That's what I meant by the first paragraph, but maybe the title was misleading. I updated it just in case