Creating and Animating a Modal Component as a Child Route Using Vue
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. That might sound confusing, so here’s an embedded Code Sanbox you can play around with.
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.
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
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 .
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.
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.