DEV Community

Ramsay
Ramsay

Posted on

Creating and Animating a Modal Component as a Child Route Using Vue

Here’s a link to the repo.
Here’s a live demo.

As I work on side projects, I sometimes stumble upon a pattern that I really
like. This is one of those times. Today, I’ll show you how to implement a detailed view of a list item as a modal using a child route.

If you play around with the live demo you'll notice that the URL updates when a rule is clicked on and a modal renders. This means that we can refresh the page and the modal will render with the list of rules in the background. It’s a nice touch because we’ll always be able to see the rule in the context of the game.

The Router

We have a parent route called Game that has two child routes — Game Rules and Game Rule. I’m using a separate route for rules, because eventually I’m going to let user’s create groups of rules called rulesets, and I would like to be able to separate that out as another route, eventually.

Of note, the Game Rules route renders only one component for the page view (lines 24–26) while the Game Rule route also renders the RuleSingle component for the rule view (line 36). This will make sense once you see the GameSingle component.

Also of note, we’re leveraging router meta which will be used in the GameSingle component to determine if the modal should be shown. We want it to show for Game Rule but not for Game Rules.

The GameSingle Component

I’m excluding all the styling from the following components for brevity’s sake.

This component has two <router-view> tags, one for the page (line 10), and one for the rule (line 15). Note that the <modal> component (shown below) will only be shown if showModal is true. We determine if showModal is true based on the route meta (line 31). Lastly, we’re going to want to watch the route meta value and update showModal accordingly (lines 35–39). When a user clicks on a rule, the route changes causing the showModal value to be true, which in turn renders <modal> and its children.

The Modal Component

We wrap the entire component in a <transition> and use custom functions to handle the enter and leave animation. When the modal is rendered it fades in, and when a user clicks the close button, the router goes backwards in history a step causing the modal to fade out.

Conclusion

There are many ways to implement modals. One way I’ve done this in the past is by creating a modal component in the root App component and use Vuex actions to show it and tell it what content to use. It’s always felt a bit cumbersome to me, but its definitely a viable solution. I like this solution because it doesn’t clutter up Vuex state (which seems unnecessary for this type of interaction) and still allows the modal component to be re-usable.

Top comments (1)

Collapse
 
yosie_r profile image
Yosie

Great job Ramsay! I'm trying to adapt your demo to Nuxt.js but I can't get the pages to render. I'm not sure if the problem is the difference in the routing configuration. I don't see any errors... 😕