Creating and Animating a Modal Component as a Child Route Using Vue
Tags: vue, javascript, frontend, ui
Published: 2018-02-08 16:04:46

---
title: Creating and Animating a Modal Component as a Child Route Using Vue
published: true
description: 
tags: vuejs, javascript, front-end, ui
---

> [Here’s a link to the repo.](https://github.com/ramsaylanier/vue-tutorials/tree/master/animating-child-route)
> [Here’s a live demo.](https://ramsaylanier.github.io/vue-tutorials/animating-child-route/#/)

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](https://ramsaylanier.github.io/vue-tutorials/animating-child-route/#/) 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

{% gist https://gist.github.com/ramsaylanier/e98abc704cb9fb372a75f87f60f64616 %}

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.

{% gist https://gist.github.com/ramsaylanier/f5023f11966f7d059e6f43b0e090e270 %}

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

{% gist https://gist.github.com/ramsaylanier/086d7495582e43497e77938b07e119be %}

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.