Speedy dev insights
- Creating your first Web Component in 5 minutes or less
- Two-way data binding and reactivity with 15 lines of vanilla JS
- 13 super rad web dev tricks you don't know about (but should!)
Creating your first Web Component in 5 minutes or less
Hi, I'm Chris Ferdinandi, the VanillaJS Guy.
I teach people how to build a simpler, more resilient web over at gomakethings.com.
And today, I'm going to share a series of short talks about cool, browser-native features with you.
First up, Web Components.
Web Components are a collection of technologies that you can use to create reusable custom elements, with built-in interactivity automatically scoped or encapsulated from the rest of your code.
They have a wide range of features and functionality, some good, some bad, and some ugly.
But today, we're going to look at how to create your first web component using the most cliche of examples, the counter button.
And yes, I did click that button 42 times instead of just hard coding in the number.
To get started, we'll create a custom element.
You can name it anything you want, but it must include at least one dash.
word web components are not allowed, because those are reserved for native elements.
In this case, we're going to call ours counter-button.
With this method, we pass in the name of our custom element as the first argument, and a class that extends the HTML element object as our second.
When our page loads, this will automatically find any custom elements with the name that we provided and instantiate a new instance of our class on them.
Now that we have our custom elements and we've defined them, we're going to actually render some HTML into the UI for them.
And to do that, we need to use the constructor function inside our class.
The constructor function runs when a new instance of the class is created.
In it, we'll run the super method to make sure that we have access to the parent class, which in this case is the HTML element object, and all of its properties.
Next, we'll add a property to track the number of clicks.
In this case, we're going to call it count.
We're going to attach it to this, the current element being instantiated by this class, and we're going to give it a default value of zero.
And finally, we'll use the innerHTML property to render a button into the custom element, which is the item assigned to the this keyword, and we'll include our countState property as part of that text.
Now a button is automatically rendered into the UI whenever we include our custom element.
If we jump over to the browser, you can actually see I have three buttons.
one says clicked 0 times as its default value.
When the button is clicked, we want to increase our count by 1 and update the UI.
Web Components have a handful of lifecycle functions that run when various things happen, just like a lot of state-based UI frameworks do.
One of those, the connected callback function, runs when the custom element is loaded into the DOM.
We'll use that to add a click event listener on our custom element.
In this case, we need to save this to a variable because we need to be able to access it inside our callback function.
Inside that callback function, we are going to increase our count state by one, and then we're going to use the text content property to update the text inside our button to display the new count value.
Now whenever a button is clicked, the count and the UI are automatically updated.
If we jump over to the browser and I click, you'll notice each button maintains its own state and clicking or toggling one button doesn't affect the others, but the UI automatically updates.
And with that, you've just created your first web component.
You can access the source code from this talk and dig deeper into web components over at gomakethings.com/sotb.
And I'll be back later with another Speedy Dev Insight.
Two way data-binding and reactivity with 15 lines of vanilla JS
Hey, Chris Ferdinandi, the Vanilla JS guy, back with another speedy dev insight.
This time, I want to show you how you can get two-way data binding and data reactivity with just 15 lines of Vanilla JS.
Let's imagine that we have two forms on our page. They both have the same fields in them, but they're in two totally different locations.
When someone types in one, we want to automatically update the corresponding field in the other form.
If we look at the HTML for our forms, we'll see that each one has an identical name attribute, so that first field has a name of title in both forms.
But because IDs must be unique and only used once, the IDs on each field are varied from one form to the other.
For this challenge, we want to use what's called two-way data binding.
What that means is that whenever one of our form fields is updated, we want to update some data object with its value.
And whenever that data object is updated, we want to update all of the corresponding fields with that value too.
A proxy object is a wrapper around an array or object that watches for changes to the object properties and lets you automatically run code in response.
We'll create a new proxy with an empty object by using the newProxy constructor.
We also need to pass in an object of handler or trap methods as a second argument.
We'll pass in an object, and for this one we only need a single trap method, set.
This runs whenever a property value is added or updated.
The proxy API has a ton of these, but for this particular project, we just need set.
The default behavior for this method would be to update the object key with whatever value was provided and then return true.
You can see this method accepts a handful of arguments, the object being updated, the key to update, and the value to update it to.
To update our field, whenever the data object is updated, we can use the querySelectOrAll method to find all of the fields whose name attribute has a value equal to the object key that we're updating.
So in this case, I'm going to pass key equal or name equals and then the key that we want to update into the querySelectOrAll method and assign it to the fields variable.
And then we can loop through each of these fields and update its value to whatever value was passed into the set handler. Now if we update our data object, our form fields get automatically updated too. Let me jump over to the browser and show you.
If I open up the console and I type in data title equals "So long and thanks for all the fish," you can see that the title on both of our forms is automatically
updated in response.
To keep both of our forms in sync, we need to also update this data object whenever one of our fields is updated. And we can do that using an input event listener.
So we'll attach this to the document so that we can listen for all input events that happen on the page. And inside the callback function, we'll use the closest method to make sure that the field that updated, the event target, happened in one of our data form sync forms.
And if it didn't, we'll use the return operator to end this callback function early. Otherwise, though, we can update our data object with the name of the field and the current value of that field.
And when we do this, this will update our object, which will cause the proxy argument to run our set handler function, which will update all of the other fields to match.
So just as an example here, how are you today? We can update the title with nice to see you.
And you can notice as I type in one of these fields, the other field automatically gets updated to match.
You can access all of the source code from this talk and learn more about two way data binding and state-based UI over at gomakethings.com/sotb.
13 super rad web dev tricks you don't know about (but should)
Hi, Chris Ferdinandi, the VanillaJS guy here with one last speedy dev insight.
Here are my 13 favorite web developer tricks.
If you need to listen for the same event on lots of elements, you can attach your listener to a parent element to catch all of them, and then filter out events that aren't on the element that you care about.
Not only is this easier to manage as a developer, but it's actually better for performance.
early return pattern.
Lots of nested if statements can quickly become unruly and hard to read.
As an alternative, you can check for the opposite of the desired state by prefacing your test with the bang or exclamation point operator.
Then you run the return operator when that check returns true.
For bigger functions, this results in code with far fewer indents and an easier to read structure.
Multiple Selectors For methods that accept CSS selectors, you can pass in multiple selectors as a comma-separated string, just like you'd write them in CSS.
You can use these attributes as standalone selectors.
You can also use this to make event delegation easier in bigger apps where you have different functions that run for the same event.
With this approach, you would store all of your event handlers in an object, and then you can use the handler name as the value of the data attribute.
In my event listener, I can get the value of that attribute, and then I can pass that value in to run the matching function.
Converting an object into a query string.
To convert an object into a query string, you can pass it into the new URLSearchParams constructor, and then run the toString method on it.
Removing duplicates from an array.
The set object is a lot like an array, but each item in it must be unique.
If you pass an array of duplicate values into the new set constructor, and then convert the returned set object back into an array, you get a new array with all of the duplicates removed.
Generating Random IDs The crypto_random_uuid method generates a random, cryptographically secure unique ID.
For example, plain objects, arrays, dates, regex patterns, and null all return object with the type of operator.
For more accurate type checking, call the object prototypeToString method on the item you want to check.
The returned value will start with square bracket object followed by the actual object Type.
Looping over objects.
A for in loop is often used to loop over objects.
To get the value of a particular key, you need to use bracket notation to get that key value on the object you're looping over.
A cleaner way to loop over objects is by pairing the object_entries method, which converts an object into an array of key value pairs, with a for-of loop and array destructuring.
Object property shorthands.
Simpler Boolean Returns.
A lot of my students will write code that explicitly returns true or false based on some condition.
And there's nothing wrong with that.
It totally works.
But if the conditional check that you're running returns a Boolean itself, you can return the check itself rather than an explicit true false value because the check you're running is doing that already.
Tip number 13.
The correct way to pronounce this word is GIF.
About Chris Ferdinandi
He loves pirates, puppies, and Pixar movies. Learn more at GoMakeThings.com.