It’s important to note what I stated above. We will be looking at a different approach, not a new one. While the example I will be using is written in ES2015 there’s nothing new or groundbreaking about it. It just might take a different approach than what you might normally see.
On many of the projects we work on here at WDS, there is almost always a requirement to have at least one modal and in some cases even multiple modals on the same page. While this may seem simple to implement, there are a lot of questions and observations that should be taken into consideration.
- What is going to be the trigger for opening a modal?
- If there are multiple modals on one page, then we will need multiple, unique triggers.
- What will be the close trigger for each of the modals?
- What will be the contents of the modals?
- Will the content be created on the fly, or will it be markup that has already been rendered to the page but is just hidden?
- How can we nicely present the modal?
- Implementing a nice animation into a modal can be tricky!
- Do you need to apply a CSS class to another element on the page when the modal is open and the remove it when the modal is closed?
What I’m trying to point out here is that the modal we’ve ended up writing is not very reusable from project to project. Sure, you might be able to take bits and pieces of code and move them from project to project, but in the end, you are creating a unique solution for each new project.
Let’s explore a different approach! One that would allow for code reuse across projects.
Building Reusable Components
The concept that I’d like to drive home in this post is to start thinking about building reusable components that are powered by their API. I’ve really learned a lot about this concept by learning React and Redux. Feel free to check out the experimental WordPress theme I built using React and Redux.
You don’t need to be using any fancy frameworks in order to implement the idea of building reusable components. To be honest, the thought of having a UI component such as a modal that has default options you can override and callback functions you can tap into is super exciting!
For this post, we are going to focus on building a modal UI component in vanilla ES2015 that is reusable. This isn’t going to be a full-blown solution, but it will hopefully be enough to show the power behind building reusable components that expose an API for powering them.
Since we will be using ES2015, let’s start by scaffolding out a class that we will use for our component:
Next, just like in PHP, the constructor function is going to be run each time the Modal class is instantiated. Our Modal class will take two parameters. The
openTrigger will be the HTML element that triggers opening the modal and the options parameter will be the options we pass in to override the defaults.
You will notice in the code above that we are using
Object.assign(). This is an exciting new method in ES2015 that allows for merging two objects. I would encourage you to read and learn more about Object.assign(). Anyways, we are just merging the options object being passed in with the default options provided.
For this example, we are going to use a new ES2015 feature called template literals to create the markup needed for our modal. Notice how we are able to display variables right inside our template literal strings.
Next, we will need a
render() method that will be responsible for putting together the template and attaching it to the DOM. As you can see, we are using a document fragment to build out the markup. A document fragment is a minimal document object that isn’t actually a part of the DOM. It’s a performant way of composing some markup in memory then attaching it to an element.
Now we need open and close methods. These two function will be somewhat similar, but let’s touch on a few key points.
First, both functions check to see if a callback function has been passed in via the Modal options. For the
open() method the callback that is checked for is
this.config.onBefore() and for the close method the callback checked for is
this.config.onAfter(). If either has been set, it will be called.
Second, we are utilizing a
setTimeout() function along with arrow functions to add and remove CSS classes that will help us animate in the modal. This perhaps isn’t the best solution here, but for the sake of this example, it works just fine. You could explore using transition or animation events as other possible solutions.
The last function is a simple
bindEvents() function that’s sole purpose is to bind the
open() function to the open trigger specified by the user.
Now that we have our modal class built out with the basic functionality we can now create a couple of different modals that will work independently of each other.
Here is code that will instantiate two different modals. Each will have a different
openTrigger parameter as well as different options.
First, we are declaring two different button elements that will act as our modal triggers.
Then we ‘new-up’ each modal with their respective trigger button, as well as their custom options. Notice how I am writing an anonymous function that will be called in our
Check out this CodePen for a working demo.
Feel free to leave a comment below to further the discussion!