Tvinder — Tinder for TV shows

Today we are going to learn building a Javascript application with Vue.js. The application we are going to build together is called Tvinder — Tinder for TV shows.

You can find the demo application here, and you can find the Github code here.

This tutorial has two parts. In the first part, you will learn:

How to bootstrap a Vue app using plain Javascript How to create a component How to track states using data How to pass data across components using props How to add methods to component

bootstrap the app

First, let’s start a new folder following the structure below. The finished_app directory is a reference point of what the final project looks like.

We are going to create main.js which will look like so:

((() => {

const App = window.App

const Vue = window.Vue



Vue.component("tvinder-app", App) new Vue({

el: '#app',

data: {

hello: "world" }

})

}))()

Lets break down what’s going on here.

const App = window.App

const Vue = window.Vue

These two lines are getting a reference to Vue and something called App which is simply a property we added to the window object in another file ( app.js ).

Vue.component("tvinder-app", App)

Next we register a component with Vue to be used later. This will be covered more later, and in fact will be done slightly differently.

new Vue({

el: '#app',

data: {

hello: "world" }

})

new Vue() is the entry point of our app and attaches it to an element on the page that we define (in this case #app ). If you look at index.html , you will notice that #app is a div that wraps our app.

What is neat about this is that you could have a small Vue app living inside a larger web application by simply bootstrapping an id on an element within that larger web app.

movie-data.json is a file with some data that we will be using later on. app.js is our application javascript file which can be changed later. index.html is the entry point into our app. I do want to point out one thing:

<script src="src/components/app.js"></script>

<script src="src/main.js"></script>

We must load all of our components before loading the file that bootstraps the application. If we don’t then when Vue is doing its thing it will not know that about any components that we have made.

And of course we have vue.js , the star of this show!

<!DOCTYPE html>

<html>

<head>

<title>Tvinder Workshop</title>

<script src="src/assets/vue.js"></script>

<script src="src/assets/vuex.js"></script>

<link rel="stylesheet" type="text/css" href="src/assets/stylesheets/tvinder.css">

</head>

build first Vue component

What is a component? From the official documentation:

At a high level, components are custom elements that Vue’s compiler attaches behavior to.

There are three main parts to a component. They are the template , the script , and optional styling .

Template: the HTML markup for a component.

Script: This is where all of the Javascript that defines a components behavior lives.

Styling: This is the CSS styling for a component.

You can leverage Vue to create these components in different ways. With more advanced package manager such as Webpack we can build Single File Components. However in order to construct components this way you will need to compile them. We can build the components more simply using plain Javascript which is what we will be illustrating here.

Let’s register our first component. We will be adding the Header of our app. First we will create a javascript file for our component. src/components/header.js Inside this file we will add two important pieces of information for our component. The template and the script.

src/components/header.js

((() => {

const html = `

<div class="header">

<div class="header--left">

<h1>tvinder</h1>

</div>

<div class="header--right">

<h1>votes</h1>

<div class="header__data">

<h1>0</h1>

</div> </div>

</div>

`



Vue.component("app-header", {

template: html,

})

}))()

There are more than one way to define the template for a Vue component. Here we are simply defining a string of HTML and setting it to a variable, and then telling the Vue component to use this string as the template.

The other important part of this file is Vue.component() . Here we give the component the name of app-header and define what the template will be. Other component behavior will also be defined in this component. We will discuss this later.

Now that we have a component to render, we need to load it into our app. Add a reference to the component <script src="src/components/header.js"></script> to our index.html in order to load it.

index.html

...

<body>

<div id="app">

<tvinder-app></tvinder-app>

</div> <script src="src/components/app.js"></script>

<script src="src/components/header.js"></script>

<script src="src/main.js"></script>

</body>

...

Next we need to render the loaded component. Add <app-header></app-header> to our app.js component.

src/components/app.js

((() => {

const html = `

<div>

<app-header></app-header>

</div>

` Vue.component("tvinder-app", {

template: html,

})

}))()

Presto! That is it, our first component.

add data to component

Data is an important part of components because they keep local states that are rendered to view. One important gotcha with data on a component is that it must be a function. For example:

data: function () {

return {

someKey: SomeValue

}

}

If you look at the markup for the app-header you will see that we have hardcoded a 0 as the value for our likes. This is not very useful... Instead we will declare some attribute in our data object that we will use to render the amount of likes. We will be able to manipulate this data in our app and dynamically display the number of likes we have.

Let’s add the data function to our component.

src/components/header.js

data(){

return {

likes: 0

}

}

Here we use key value pairs on our data object to set an initial value for likes. Next we will use data binding to render this value in our template.

src/components/header.js

...

<div class="header--right">

<h1>votes</h1>

<div class="header__data">

<h1>{{ likes }}</h1>

</div>

</div>

...

The way you bind data in Vue is with the double {{ }} . Inside the curly brackets, all you need to do is include the name of the attribute you want to bind to.

use props to pass data

Now that we have successfully built out our first component and learned how to bind and render data, we will look at one way we can pass data between components. We will learn how to pass data as a Prop from one component to another.

In Vue, every component is a standalone instance. It is isolated and has its own scope. This means that any one components cannot directly reference another component’s data. In order to pass data from a one component to another component we use a custom attribute called props. Props are an example of one-way data binding between a parent and child component. So what does this mean? From Vue documentation:

when the parent property updates, it will flow down to the child, but not the other way around

To declare a prop on your child component you must first make a reference to the custom Vue attribute. You do this by adding the following to your component:

props: {

// Props go here.

}

Inside this attribute, you define the prop you will be recieving from the parent component. There are a few important pieces of information you can set inside this definition. Here is an example:

props: {

someString: {

type: String,

required: false,

default: "Hello World"

}

}

This is all you need to do on the child component to declare a prop. The last thing to do is to pass in the prop to the child component — from the parent component — in the template.

Let’s apply props into our app. We are going to be rendering movie information; it would be overkill for the component that renders the movie information to know about the entire set of information. So this is a good spot to use props — to pass down only the movie information that we care about!

First we create a new component movies .

src/components/movies.js

((() => {

const html = `

<div class="movies">

</div>

` Vue.component("movies", {

template: html,

})

}))()

Next we add the prop we want to receive from the parent component. To start let’s just capture an image url and render that on the page. So we will declare a prop called image_url and we know that the url is a String .

src/components/movies.js

((() => { const html = `

<div class="movies"></div>

`

Vue.component("movies", {

template: html,

props: {

image_url: {

type: String,

required: true,

}

}

})

}))()

we need to pass this data to our movies component. We will render our movies component in the app component. So we will places it inside the markup, and pass the "image_url prop. Here you can see the value of the prop is also image_url . Actually we are setting the value of image_url inside the data of this component - image_url: "https://goo.gl/Puw6Ar" . This will be useful for us later when we want to change the value of image_url on the fly.

src/components/app.js

((() => {

const html = `

<div>

<app-header></app-header>

<movies :image_url="image_url"></movies>

</div>

` Vue.component("tvinder-app", {

template: html,

data(){

return {

image_url: "https://goo.gl/Puw6Ar"

}

}

})

}))()

Last but not least we need to render the image! To do this we just need to add some HTML to display the image.

src/components/movies.js

<div class="movie-poster-container">

<img class="movie-poster" v-bind:src="image_url">

</div>

Now we are using props to render an image!

add methods to component

In this step we will be creating our first method and triggering that method from the web page. Methods are another Vue custom attribute. We use methods to define the behaviors of a component. All methods are housed in the methods attribute within a component.

methods: {

// My methods go here.

}

Inside methods we can declare functions. For example, let’s say we had a calculator component, we might need a method to do some addition or subtraction.

calculator.js

methods: {

add(a, b) {

return (a + b)

},



subtract(a, b) {

return (a - b)

} // Other useful methods ...

}

You can use methods inside other methods by using a reference to this . For example:

talk.js

methods: { say() {

this.phrase("I'm Pickle Rickkkk!")

}, phrase(somePhrase) {

alert(somePhrase)

}

// Other useful methods ...

}

Let’s wire up some methods in our component. Let’s start with something simple. We can make a link to click, that will alert some text in our window.

First let’s make an actions component that will contain all of the interactions we want to have with the app. This will be helpful to us later as we continue to add more and more pieces.

src/components/actions.js

((() => {

const html = `

<div class="actions"></div>

`



Vue.component("actions", {

template: html,

})

}))()

Next we will add our methods attribute and a simple method.

src/components/actions.js

((() => {

const html = `

<div class="actions"></div>

` Vue.component("actions", {

template: html,

methods: {

myFirstMethod() {

alert("I have been clicked!")

}

}

})

}))()

Finally let’s fire off this method from a link on the webpage.

src/components/actions.js

((() => {

const html = `

<div class="actions">

<div class="controls">

<a id="skip" href="#" v-on:click.prevent="myFirstMethod" class="icon-button">Click Me!</a>

</div>

</div>

` Vue.component("actions", {

template: html,

methods: {

myFirstMethod() {

alert("I have been clicked!")

}

}

})

}))()

Let’s take a step back and look at the what is happening in the template. v-on:click.prevent="myFirstMethod" Here we are using the v-on directive for event handling. Events will be touched on more in the next step, and v-on is a little out of the scope of this project. But in simple terms, this just means, on - click triggers myFirstMethod. So when this link is clicked, the myFirstMethod function will fire off!

Continue to part 2

That’s the end of part 1! We covered a lot of stuff in part 1 and make sure you understand it before moving on to part 2!