Build A Movie Player with Vue.js (Solution to Code Challenge #5)

March 13, 2018 0 Comments

Build A Movie Player with Vue.js (Solution to Code Challenge #5)



Last week, we got on the code challenge #5, in which we were required to create a simple movie player using data of movies from a provided API.

You can check out awesome entries for the challenge using the hashtag #scotchchallenge on twitter or check the comments under the post. In this post, we shall be solving the challenge using Vue.js.

Why Vue.js?

Vue is a popular and fast-growing progressive JavaScript framework that offers the much-required flexibility and simplicity to build out awesome user interfaces.

Table of Contents

The base code consists of HTML and CSS, written to structure and style the movie player.


The app is structured to have a container div in which we place the video display and the thumbnails to select the video as separate child divs.

<div class="videos-container" id="app"> <div class="video-player"> </div> <div class="video-choices"> </div>


In styling the app, CSS was used with the SASS variant and Flexbox was mostly used to position the elements accurately.

body { background: #1e3c72; background: linear-gradient(to right, #1e3c72, #2a5298); padding: 30px; min-height: 100vh; display: flex; align-items: center; justify-content: center;
} .videos-container { background: #333; padding: 10px; box-shadow: 0 0 50px 5px rgba(0, 0, 0, 0.25); color: #FFF;
} .video-player { min-height: 300px; width: 100%; background: #000; margin-bottom: 10px;
} .video-choices { display: flex; :not(:last-child) { margin-right: 5px; } img { height: 100px; } }
.poster{ float: left; }
.thumbnails{ display: flex; justify-content: left;


For the challenge, we were provided with an API containing a list of movies and data related to each of them.

const api= ""

The Technique

As earlier stated Vue was used in buiding out the movie player interface because of its flexibility with handling data and passing this data to the DOM. In building this player, we split each part - the movie display and the thumbnail, into components to keep our code tidy and also for probable reusability.

The Components

The first component created was the <video-frame> component.

const videoTag = { template: ` <iframe allowFullScreen frameborder="0" height="376" :src="source.trailer" style="width: 100%; min-width: 750px" />
`, props: ["source"]

In the component, we defined the template as well as stated all props used by the component.

Props are used to pass data from parent components to child components in Vue applications.

The component's template consists of an iframe with which we shall embed all video links.

Next, we created the <video-thumbails> component to display all thumbnail images for each movie.

const thumbnail = { template: ` <div class="thumbnails"> <div v-for="movie in movies"> <div class="poster" @click="changeCurrent(movie)"> <img :src="movie.poster" height="200"alt=""> </div> </div> </div>
`, props: ["movies"], methods: { changeCurrent(movie) { this.$emit('choose-movie', movie) } }

The <video-thumbnails> component is an object containing a template, props declaration and a list of methods utilized in the compoenent.

In the component's template, we utilize the list rendering Vue directive v-for to render each thumbnail in a list with identical divs. In each thumbnail, the poster of each thumbnail is displayed and an event directive is used to specify a function to be called once the div of each thumbnail is clicked. We shall proceed to create this function.

In the methods object, we created a changeCurrent() function which takes an argument of the current movie clicked. In the function, a custom event - choose-movie is emitted to the parent element with a second argument which is the movie selected. So whenever a poster is clicked, the action is sent to the parent <video-thumbnails> div which is watching for any choose-movie event emitted by child components.

While props are used to pass data from parent to child components, $emit is used to send events/actions from the child component to the parent.

Managing Data

We created a Vue instance to utilize the components created as well as fetch and manipulate required data.

var app = new Vue({ el: "#app", components: { "video-frame": videoTag, "video-thumbnails": thumbnail }, data() { return { api: "", movies: [], current: null }; }, created() { axios.get(this.api).then(res => { this.movies =; this.current = this.movies[0] }); }, methods: { handleChangeCurrent(movie) { this.current = movie } }

We created a Vue instance and mounted it on the DOM element with the app id. Next, we defined the components created and a data function which returns an object that holds state data. The data function can also be written explicitly as an object but using a function which returns an object allows room for the creation of variables in the data function. We can use these variables to manipulate the returned object's values.

In the data object, we created a key holding our API URL as its value, an empty movies array to hold the fetched movies and a current variable to hold a value for any selected movie.

To fetch the data contained, we used Axios, a promised based HTTP client. The Vue lifecycle method created(), makes a get request using Axios to our API, fetches the movie data, and assigns this data to the movies array created previously. Also, the current movie to be displayed is set to the first movie in the list of movies fetched.

To handle the selection of a new movie from the thumbnails, a function handleChangeCurrent is created. This function receives an argument of the current movie data selected and assigns the value of state data current to the selected movie data.

Putting these together, our HTML script becomes:

<div class="videos-container" id="app"> <div class="video-player"> <video-frame :source="current"></video-frame> </div> <div class="video-choices"> <video-thumbnails :movies="movies" v-on:choose-movie="handleChangeCurrent"></video-thumbnails> </div>

Notice how we passed current as props to the <video-frame> component with the source attribute. Also, the movies array is passed to the <video-thumbnails> component in the same manner and the custom event choose-movie triggers the handleChangeCurrent function.

Here's the final product.


We built a minimal movie player using Vue. Features used include props, custom events, emits, and components. While completing this, feel free to make use of other frameworks or tools, let's look forward to the next awesome challenge. Happy coding!

Tag cloud