Learn Vue.js – Full Course for Beginners – 2019

Welcome to the course. My name is Gwen, 
and I'm a software developer. Here is the   itinerary for today. Part One will start in the 
browser to get a feel for the syntax. And part   two will be on a local computer building 
apps as you regularly what. Along the way,   we'll cover different bits of the view API so you 
can get started right away. First, let's define   what view is. On a basic level. It's a front end 
library to help you build JavaScript applications.   Now Vue js is more robust than something like 
jQuery, since it gives you specific recommended   patterns for code organization. Although it did 
borrow a lot of good ideas from jQuery, Angular,   React, and others. It's usually not found in 
the wild by itself, you'll see it used with   lots of other libraries and combined to make 
sort of a framework and alternative to react,   Angular, and others. And we'll cover many of 
these libraries today. So let's get straight   into it. I'm here my browser at JS fiddle dotnet 
is just another place to put front end code.

And   I'm going to try hello world. So this is if I was 
just writing a plain HTML or jQuery application, I   might put something like this. So how do I attach 
this to the view instance? Here, I've reloaded   the view library. So I can just choose it from 
frameworks and extensions, I'm just pulling in the   latest version. And from that library, I have a 
view instance. So I can instantiate it like this,   and then pass it an object of options. The only 
required option I have to set is element. So which   element in the DOM do I want to attach my view 
instance to going to attach it to route.

And then   of course, I need to have a root element with ID 
of root here. So now my view instance is attached   to this div in the DOM. If I run it, of course, it 
doesn't do anything different. So let's make it do   something different. There's also a data object 
I can use. And I can populate this with variables   to use in the DOM. So I can say data greeting. 
Hello view. Now how do I put this in the DOM   view has something called double mustache mustache 
syntax.

So anything inside of this inside of these   double curly braces view looks at a more parse 
as JavaScript. So view comes down here and says,   Okay, I have a variable in data called greeting. 
And so I'm going to render the contents of   the variable, we run this again, changes to 
Hello view. Another important concept in view   is data binding view uses two way data binding 
through a directive called v model. On an input,   when I put v model, it binds it to a variable in 
the data object that I give it.

So in this case,   I'm telling Vue to bind this value of the input 
to the greeting variable from data. If I run this,   everything inside of my input is the same as 
the greeting variable. And then if I change it,   it live updates. extremely simple. The model 
is something called a directive. There are a   lot of directives in view, and they're used to 
interact with the DOM.

Let's look at another   common directive. V if V f evaluates an expression 
to a boolean value, either true or false. So let's   start with something that we know is true. So if 
one equals one, you're telling view to display   this div and render it to the page? Yep. So this 
isn't so useful, it's usually used in combination   with data attributes here. So let's make a new 
data variable, we're going to call it count. So   if count equals one, then display this diff to the 
screen. So put my changes to count equals zero.   And of course, it won't display to the screen. 
Now there are other directives that you can chain   called v. Else if and V else just like an if else 
statement. So let me change these. Orange, just   different values red.

Let's say if count equals 
two. So this is pretty self explanatory. If count   is one, nope, if count is to render this, anything 
out, other than that render v else. So if I put   two, it's going to render red, and so on. Now, the 
thing to note about vi if these divs, if they're   not true, they don't get rendered to the DOM at 
all.

Now, this might be the behavior you want, and   many times it is view also has another directive, 
called v show. So let's call this the show. There,   we'll just do the same thing. If count equals 
one, change Capital One, run, and it's green. Now,   this time if count is two, of course, nothing 
displays here. But it's actually still being   rendered to the DOM, just with display none set in 
the CSS. Have you look in here to kind of dig in,   but you can see that there's a div with green 
inside this our same div up here. And it's set   to style display none. So it's still in the DOM 
here. And so sometimes you want to use v if and   sometimes you want to use v show, it depends 
on what you're doing in the application. And if   you need better performance if you're constantly 
adding and removing things from the DOM.

So let's   look at some more directives. I've already typed 
this out to save some time, it's just an input   with a submit button. You click it it alerts. And 
also an email variable that is bound through the   V model directive to the what's entered into the 
input. To view has this directive called v. Bind,   a V bind can take an HTML attribute, like 
disabled, that works in vanilla HTML,   and parse it as JavaScript. So email that links 
will say is less than two. So what this does is   the regular HTML attribute disabled with disabled 
this button, but we're telling view to parse this   as JavaScript, so we're going to take that email 
length, and the button will be disabled only if   the email length is less than two.

If it's greater 
than two, then the button will be enabled. So   let's run this. And you can see I can't click on 
it, it's disabled. But if I type something here,   now it's enabled again. So you can do this on 
many different attributes, not just disabled.   And there's also a shorthand, which is what 
you'll usually see in view applications. So   it will be just whatever HTML attribute preceded 
by a colon and that's shortcut for saying v bind   colon because it's so common in view. Now, another 
use for V bind that's common is to dynamically add   classes. So, Stu colon, the shorthand for V bind 
Last. And then there's two different ways of doing   it, I'm going to start with the first syntax, 
which is called object syntax.

So I'm going   to dynamically had this read class. And I'm going 
to say, if the email dot length is less than two,   I want to have a border, a red border around this 
input box. So let me run that. And I have a red   border. And as soon as I get past two, or I get 
two or greater, then I don't. So that's how you   can dynamically toggle classes. So there's another 
syntax used if you want to toggle in between two   different classes, which is array syntax. So we 
can use just a regular JavaScript ternary here.   So email dot length, is let's say, if it's less 
than two, then we're going to use the class red,   and if it's greater than or equal to two, will 
be the class green. So let me run this. And we   had the class red. And now it toggles back and 
forth in between green.

There are several other   directives in view, these are a bit less common, 
but I just want to mention some of them. So we   already know that we can put variables in the DOM 
using the double mustehsan mustache syntax. If I   run this, I can type and it shows up, I can 
actually do the same thing using a directive   called v text. When you put a paragraph tag, the 
text equals email, and then just close the tag. So   if you're used to jQuery, you'll be used to the 
dot text that it uses to put text inside of an   HTML element.

This is doing the exact same thing. 
So if I run this, it does the same thing as using   double curly brace. There's also the HTML, which 
will parse it and we'll just put text inside. But   it will parse it as HTML, similar to the dot html 
and jQuery. So if I type stuff in, it does the   exact same thing. But I can also type in HTML 
tags. And it parses it as HTML. So what if you   want to render something just once a static HTML? 
Well view has another directive called v once, say   once and put the email in here. Just to compare, 
I'm going to copy this and put it outside of the   ones.

So let me start with something initially 
here. So as I update this, it only changes in   the second one because it's frozen and just set as 
the static HTML of whatever it was initially. The   second one will still display and update as you 
change the V model for that variable. So let's   look at looping and view. I'm just going to clean 
this up real quick. of all of this. And let's make   a list an ordered list. No I. And the directive 
to handle looping in the DOM and view is called v   four. So let me come down here and get something 
to actually loop through, which is an array of   cats have already written. Paste it there. And 
the syntax for this will be you need to take   care of a cat's and you're gonna say, item in 
items. So it will just be like a four in loop   in JavaScript. So you'll say cat in cats. And 
then during every iteration of the loop, you'll   have access to the cat variable which will be 
Per index in the array.

So I'm just going to put   cat here and run this again. And it comes out with 
all the different cats in the array. So of course,   in the first iteration, it displays in Li element 
with the first cat inside, which is kick cat,   at index zero, and then it moves the loop 
moves to index one, and then index two,   and so on, and so on. And if you look, in the dev 
tools, you can see it has the full array there.   Now, you can also do this with objects, of course, 
these are just simple objects with one key value   pair each. So now cat would equal this object with 
the name inside. So to display the cat's name,   now, I'd have to do cat dot name. Run it, 
and I get all my cats. Great. So there's   more we can do with looping. And there's 
more we'll get to later when we're looking   at local applications. But that's pretty much 
how it works. So let's look at functions. Now,   what if we wanted to add a new item to this array. 
So I'm just gonna add something similar to what   there was before with an input.

The model was new 
cat, button. So I'll add a function to the button   in a second. Let me run this, and it renders my 
static HTML. That's good. Let me add this new cat.   So this is modeling my new cat that I'm going 
to add to this list. So I need some kind of a   function to add it for me. And I can do that with 
a directive called v on on click, so when I click   this button, I want it to perform an action. In 
this case, I want it to run the function ad Kitty,   which we're about to make. So the data object is 
just four variables. So to put a function here,   I need to add one called methods. And this is 
another object with functions inside. So add   Kitty, oops, and Kitty, which is a function. And 
I'm going to need to push a cat on to this array   to add it to this array.

So I can access any 
any data variable inside of a method by doing   by using this. So this dot, cats will access my 
cats array in data here. So this cats dot push,   and then I want to push my new cat and my new cat, 
I also have access to this. So I can say this dot   new cat and I have the new cat's name. Of course, 
this would work if we had just a plain array,   but we actually have an array of objects. So I'm 
going to put this inside of an object and then   say, name is this dot new cat. So this will push 
another object on to this array. So let me see if   this works. ran it. Let me add and I can't press 
Enter right now.

But when I click the button, it   adds it pushes on to my array perfect. Of course 
it's kind of annoying to click Add every time. So   what if I want it to respond to an enter as I'm 
typing, so I can quickly add more kitties. I can   actually add another event with V on again but in 
this case I want v on key up and then equals add   kitty so I want to run the function add kitty on 
kiya. So let's run this and see What it does. So   unfortunately, though, I didn't tell it which key 
up. So any key that I press is just adding a new   cap for each one, which isn't the functionality 
that I want.

So I can modify this key up by saying   key up dot Enter. And we run that their key up 
dot enter. So I have to hit Enter, and it adds   it to the array, which is perfect. Unfortunately, 
it's not really the functionality that we want to   leave the same cat in the input box. So how do 
we clear the input box, we can just set new cat,   this, that new cat equals an empty string. We've 
already pushed the new new cat so we don't need it   anymore.

And this new cat is fine to be emptied 
again. So let's run this. There. And now MTS,   ready for more cats. So there's many more events, 
and modifiers that you can chain on to events.   For example, view has an API for chaining things 
on to the click event, you could do dot prevent,   which means prevent default. And you can also do 
stop for stop propagation. Basically all of the   common things you might do, that are associated 
with that type of event, which is super useful. I   want to show one more shortcut here. And this is 
what you'll normally see in a view application,   instead of V on because it's so commonly used, 
they have a shortcut to just do at. So at click,   and then you can do this with any type of event 
anywhere you would use vi on. So you can say   key up. Let me just show that this still works. 
And it works fine. Both ways work, this is just   adding a shortcut to it. So let's say you want to 
update something that's rendering to the DOM view   has something called filters.

So I'm just going 
to write a simple filter to illustrate what it   does. And I'll come down here after methods, I 
can add another object. And this one is similar   to methods. It's an object of functions. And I'm 
going to put the function capitalize function and   actually a value here and I'll return the value 
but I'm going to change it to uppercase. viewable   will parse this as JavaScript with cat dot name, 
and then it will pipe it to this capitalized   function, which is a filter. So it doesn't change 
the actual value stored in the view state here in   the data property. So all of these names will 
still be lowercase, but just the display on the   DOM will be piped through this capitalize 
function. And it will come out value that   to uppercase. So if we run this. So I actually 
misspelled filters here and the add ins. And there   you go. It filters through the capitalized so 
you can also pipe these.

So I'm going to add one   more catify. And I'll make another filter here. 
function value. And I'll return the value plus y.   So run that and it returns y on the end. If I 
piped it the other way the y would be capitalized.   Really this isn't used that often in view. In my 
experience, it's just a good thing to know about   for when the need arises. Another set of methods 
in view for updating what's seen on the DOM,   or the computed methods.

So let me get rid of 
filters real quick. And this filters block here   and I'm going to add compute instead. And I'm 
going to use the same and scroll down. And I'm   going to use the same method. So let's get a fi, 
cat name, function. This time the function doesn't   have to take anything. So let's say if this dot 
new cat, which is our cat name that's entered in   in this input box. So if that the length of that 
is greater than one, I'm going to return this   stock cat name plus y. And let's display this in 
the DOM.

Killer filename. I'll put a break after.   So you probably noticed the connection, that view 
whenever it sees a variable. Inside of the double   curly braces, it looks down here at the data 
property, and the methods and the filters and   the computed and tries to find a match for it. So 
let's run this. There we go. And as I type, well,   it's adding the Y for computed but it's coming up 
with undefined. And that's because I misspelled   the variable. So I put new cat there and run 
it again. And that should work. So later on,   you'll be using computed a lot when you deal with 
view x. It's also extremely useful. If you have a   lot of logic in the DOM, let's say you're doing 
a lot of computation or updating inside of this   block, then you could clean it up, take all of the 
logic outside of the DOM here, put it inside of   a computed property and then just display it in 
the DOM like we're doing.

So let's say you want   to update something that's rendering to the DOM 
view has something called filters. So I'm just   going to write a simple filter to illustrate what 
it does. And I'll come down here after methods,   I can add another object. And this one is similar 
to methods. It's an object of functions. And I'm   going to put the function capitalize function and 
actually a value here and I'll return the value,   but I'm going to change it to upper case view, 
we'll parse this as JavaScript with cat dot name,   and then it will pipe it to this capitalise 
function, which is a filter.

So it doesn't   change the actual value stored in the view 
state here in the data property. So all of   these names will still be lowercase, but just 
the display on the DOM will be piped through   this capitalize function. And it will come 
out value that to uppercase, so if we run   this so I actually misspelled filters here and 
add an s. And there you go. It filters through   the capitalized You can also pipe these. So I'm 
going to add one more catify and I'll make another   filter here.

Function value. Then I'll return the 
value plus y. So run that and it returns y on the   end. If I piped it the other way the y would be 
capitalized. Really this isn't used that often   in view. In my experience, it's just a good thing 
to know about for when the need arises. Let's talk   about custom components. Vue has a component 
architecture that lets you reuse bits of code,   just like most modern, single page application 
frameworks. So let's illustrate this, I'm going   to create a new component using view component. 
And I'm just going to call it catalyst. And then   I pass it an object of options. That's it, there's 
a template. And I'm just going to do a multi line   string with. So for right now, and actually, a 
list should be inside of you.

How does this work?   Close this, I will have to attach it to my view 
instance. So I'm going to say, component. And then   given an array of components, components, same is 
catalyst. Now let's add catalyst to the DOM. So to   add any custom component that you make, you can 
just add it by its name. and run it and you can   see cat down here, you can also pass in logic 
and variables. So let's pass in our cats array   and display the array through the component. 
The way to accept variables in a component is   through something called props. I'm going to pass 
in the cats array, I'm going to say props. Cats,   actually this array.

And I'm going to pass 
in cats. And then here, I can use a V for   the for cats. And then display it has to be cat 
name. So here I actually have to pass in cats.   So I'm passing in cats. But if you remember 
here, I have to add v bind for the shortcut,   which is just the colon. Because if I don't add 
that, it's just going to treat cats as a string,   when it gets passed into the component, instead of 
treating it as JavaScript, and then looking in the   data property and getting the array. So now cats 
is set to the array of cats. And if I run this,   again, it's the same array. And it adds on 
together. So the idea of having components   is that they're reusable modular pieces.

And 
when you're developing view locally vcli breeds   a really nice project with you with a modular 
architecture that kind of handles this under the   hood for you. To wrap up here, I just want to talk 
quickly about view lifecycle methods, view will   trigger certain functions to run, which can be 
very useful when you're developing an application.   So I have four functions here created, mounted, 
updated and destroyed, and they're just logging   things. I'm going to run this. And if I look at 
the console, it shows created when the component   is created, and when it's mounted to the DOM, it 
runs mounted. Now it's been updated, because the   state in the data object has been updated.

Now 
for destroyed, it's a bit harder, because in   the small applications, instance, never leaves 
the DOM is destroyed. So I'm going to take a   function to call destroy. So I'm basically setting 
a timer for five seconds. And after five seconds,   it's going to call app dot destroy, because the 
view instance is set equal to the app variable.   So this will destroy it.

Let me run this again. 
So I see created, mounted and then destroyed.   This also means I won't be able to update anything 
here because it will be just statically rendered   HTML as it is, is no longer connected to view. 
There are many other functions that run including   before Or mounted before destroyed. And I 
think they're very well drawn out in the view   documentation, so Vue js.org, the version two 
guide. And if you look at the lifecycle diagram   section, it shows you exactly when each function 
is going to be run during the lifecycle of the   component. So this is a really good reference. 
And you'll be using these a lot as you develop   applications. Next, we're going to go over how to 
start developing applications with vcli locally.   To create a Vue JS application, we're going 
to start with the command line interface. So   if you come to see ally dot view, J s.org. And 
click on getting started. Over here on the left,   there's a link for installation.

And it prompts 
you to npm install dash G, view COI globally.   So if you copy this command and come over to your 
terminal, you can enter this and install view COI,   I've already done this. So I'm just going to check 
my version. My version is 3.1 point one. So now   I'm going to create a view app, I can do this with 
the view create command. So view space create. And   then whatever I want to name my application, 
which in this case, I'm going to call it quiz.   So it takes me through a series of prompts. So if 
you'll notice the last one, manually select so you   can select routing, testing, linting, etc. The 
default gives you just Babel and es lint and is   a pretty basic site. on top. This is a template 
I created, which I'm going to talk about how to   do later. So for right now, we're just going to 
pick the default to get started and see how it   works. It's installing all the dependencies, this 
will take a few minutes. And it creates a folder   for you called quiz with your view application 
inside.

Now, it also tells me how to run the   application. So I can move into the quiz, folder 
NPM, run serve. And it's going to run my view   application on port 8080. I'm going to copy this, 
go to my browser. And it gives me a boilerplate   application. Let's open up our application and see 
the code. I'm going to be opening up in VS code,   which is a free code editor. And you can see 
by default, it gives you a few config files,   package dot JSON, which is where you reference all 
of the code that you didn't write any third party   libraries.

And then the meat of the application 
is in the source directory. And this is where   your j s gets rendered or your view gets rendered 
to the page. So you can see it's creating a new   view instance. So it's like we did before the 
syntax is a little bit different. But it's doing   the exact same thing. It's mounting it to a DOM 
element with the ID of app. If you're wondering   where your HTML file is, it's in the public 
directory, you can see your index dot HTML and   view is doing quite a few things under the hood 
that you can't see.

So it auto injects your   script files. So it creates a bundle out of your 
main j s and all of these different view files,   it bundles them all together, and then it injects 
a script into your HTML file for you. That's one   of the really nice things about using view, c li, 
you have all of this boilerplate and setup done   for you like Webpack, and Babel. So you can just 
start building right away. If you want to look at   the view scripts, these are the different scripts 
that view is calling to run your application   locally or to build it for production or to lint 
it for you. So let's look at the application.   From the main j s. It's importing this app dot 
view file, which is the entry point of the view   application. If you look at app dot view, you can 
see that it puts a template. This isn't created   by view. This is part of the html5 standard, but 
it puts it in the same file with a script tag,   and also a style tag.

How view works is when 
you're building an application locally, you create   many different files, each with their own template 
tag containing your HTML, and then a script tag   which contains the JavaScript that interacts with 
that ah, tml. So in that way, you can divide up   your application into components, and then put 
them all together. They're all bundled into this   main dot j s and render to the page. So here's the 
first project we're going to be building. It's a   quiz application that keeps track of the number of 
total questions you have answered and the number   you got correct.

The questions are pulled in from 
an API, and displayed along with the answers. The   only user actions are to select an answer, click 
Submit. And you also have the option of resetting   the count of questions to zero. When you choose 
an incorrect answer, the color of the answer will   turn red once you hit submit, and the correct 
answer will turn green. If you get it correct,   it will only show the correct answer that you 
selected. Back in our quiz app, let's start   making components. First, I'm going to delete 
this hello world dot view which will not need   and create two new components header dot view and 
question box dot view which is wearable display   the question answers and the submit button. Inside 
of components, the only required element is to   have a template tag for HTML. You don't really 
need a script tag or a style tag.

So I'm just   going to put some dummy text in here. Question 
box. And I'm going to copy this for the header   component. And just put a header here. So the app 
component is still expecting hello world. So I'm   going to put our new components in here. Instead, 
I say header. And how header. To be able to use   the component in the template section. I need to 
add header here. It's comma, and then question   box. And now I can get rid of the hello world and 
image.

And I'm going to add the header here. As   well as the question box. All right, let me run 
this NPM run serve. In the browser, we can see   we have both components header and question box. 
So before I update any of the components anymore,   I'm going to install a third party library called 
bootstrap view. bootstrap view has a lot of built   in components and CSS already written. So we don't 
have to worry about styling. If you're interested   to see more, you can go to their docks or see 
all the components that they offer, like buttons,   different form elements, and they're rather nice 
layout and grid system, which we will be using. So   to get started. I'm going to go back, get started 
and copy this command.

It wants me to npm install,   view, bootstrap view and bootstrap. So I only 
need bootstrap view in bootstrap. I'm going to go   ahead and copy it. Go to my terminal. Let me close 
this and get rid of you. Alright, now that that's   installed, I can add it to my project in my main 
JavaScript file. I'm going to import view and then   call view dot use to add it to my application. So 
when you create view apps using the vcli this will   be in the main js file. Get add import bootstrap 
view, I like to do my relative dependencies last.   And I'm calling view dot use bootstrap view. 
Of course, this view dot use is just for the   JavaScript portion of bootstrap. So I'm also going 
to take the CSS and import it. We import bootstrap   CSS. And now I can start using These built in 
bootstrap components. So let's use view bootstrap   in the header component, I'm actually going to go 
over to the view bootstrap docs and find the nav.   And the header is not going to be a real nav in 
this application.

But just for styling purposes,   I'm going to go ahead and use this. When I switch 
to two spaces here for consistency, put a wrapper   div. Okay, someone that attach classes to it 
later. Also, now, I only want two items in here.   I want to have the name of the application to be 
something like fancy quiz app. And then a counter   for the number of correct versus total questions. 
So I'm just going to hard code this right now. And   replace these with variables. Once I have that 
part of the app working. Let me see how this   looks. Let's run the app again.

And now it's 
now in the browser. Awesome. Well, the problem   is these are links because it thinks it's an ER 
view, bootstrap thinks we're making a navbar. So   I'm just going to go ahead and disable these. 
Set of active here I'm going to put, disable,   and disabled. And then for the logo, I just want 
to differentiate the style a little bit.

So I'm   going to make it bold. Also, to offset the header. 
I'm just going to add tabs here. And this should   auto restart. Yeah, this auto restarts in here. So 
I'll go to my browser tabs added this line here.   And then I have my logo and the counter. So the 
header component is done for right now. Let's move   to the question box and go ahead and get that set 
up. So the question box is going to use another   view bootstrap component called the jumbotron, 
which is basically a page element that sets itself   out of the page like this, I'm actually going to 
copy this code with the enclosing div, switch back   to my code editor and paste it here. Just like 
before, I want to have two spaces. indent here,   just to know I always like to have this wrapper 
div around components. Because I like to make   container classes for when I use sass or CSS. So 
I would put something like question box container   here. And then reference this class to style 
this whole component. So this is a pretty plain   jumbotron.

We'll see it in our app. And it's not 
exactly what we want, because we want a question   and then answers below it. So in the jumbotron 
docs, we can actually use templates inside that   will make the component look more like this. So I 
can put the question on top, then list the answers   and have the submit button at the bottom.

And the 
submit button is another view bootstrap element   for buttons. Notice, it's perfectly fine to have 
more templates inside of the parent template,   which is your component. And you'll see libraries 
doing this using something called slots that we'll   talk about later. But for right now, I'm just 
going to copy these, go back to my component.   And I'm going to put this inside. So let's see 
what this looks like. Not too bad. I am going to   remove the header. Because we already have a logo 
on the page. And we just need to put the question   here. So this will be our question. And then our 
list of answers will go somewhere here as well as   a submit button and a button once you've submitted 
to navigate to the next question.

Let's see what   that looks like. So we'll also have to get rid of 
these which we don't want. Now let's see what this   one looks like. Perfect question list of answers 
buttons. And one more thing I want to do in view   bootstrap before I get to the JavaScript is set up 
a grid to kind of prevent these questions or the   question box from going fullscreen.

So layout and 
grid system. See the examples of how you can lay   out a page With different containers in rows and 
columns. For this, I don't have different rows.   So I'm just going to use, I'm just going to use 
the basic one here. Go back to my code editor.   And I'm going to go to here. And I want this to 
wrap the question box component. So get rid of the   extra two columns, enter, and then just copy this 
paste. And then in this column, I'm going to tell   it. So on a small screen, or anything larger than 
a small screen, I want to take up half the page,   which is six, because bootstrap basically gives 
you 12 vertical columns. So if you want half the   page, you can do six, offset, offset equals three. 
And let me show you what this is doing. So I'll   inspect element here.

And the jumbotron in the 
question box container is taking up six columns.   So if I hover over this, you can kind of see that 
the yellow part is a three column offset from the   left. And the extra white padding on the far left 
is from the container. So putting it inside a   bootstrap container just automatically centers an 
element on the page and gives it a little bit of   padding on either side. So inside the container, 
we have 12 columns, we're using six and offsetting   by three. Great now let's jump into the API for 
the questions and start pulling some actual data   for the application. Open tdb.com is a quiz API 
that we can pull questions from. They give you a   lot of nice options. Like you can browse through 
questions, you can submit your own questions,   because these are all user submitted questions. 
And they also have a pretty nice API. by filling   out this information, we can actually generate an 
API URL to pull questions from. So I think pulling   10 questions is good.

Any category, I'm just going 
to select the animals difficulty any is fine. Any   type multiple choice, just so the UI is the same 
for every question. Default encoding is fine. So   now it generates me this API URL. I'm going to go 
put it in my browser. And I can see every time I   make a request to this API, it pulls 10 questions 
about animals? I think one kind of confusing thing   with working with this API is that instead of 
putting all of these in one array, they put the   correct answers separate from all of the incorrect 
answers, which is fine, because we're just going   to take the correct answer with the incorrect 
answers, write a function to shuffle them all   together, and then match up the correct answer 
based off of what the user selects.

And of course,   every time you hit this API, it's going to come up 
with a different series of random questions that   it pulls. Let's put the API in our application 
now. So I'm in my app component now. And I'm just   going to add a function to pull in the questions 
and answers from the API. So if you remember   when we were in the browser, using GS fiddle, we 
covered something called lifecycle methods, which   are functions that get called automatically by 
view as components either get created or mounted   or destroyed, etc. So we're going to use one 
called mounted here can be a function. And in it,   we're going to use the standard fetch API, which 
is a web standard and doesn't need a library to be   imported.

So I'm going to paste our questions API 
endpoint. And then I'm going to pass an object,   an options object with the method to get from 
this. Now, that's all I really need. But I'm   going to add a dot then and take the response. So 
never say in the response, when you use an arrow   function here and say, just let's console dot log, 
this response in JSON format, JSON. Alright, let's   see what this does. Let's run this. By the way, 
don't mind any of this orange text that says which   git branch I'm on and I'm trying to put different 
parts of this tutorial on different brain I'm   going to do NPM, run serve again. Nope, we have 
an error. Oh, it's just complaining that I'm using   a console dot log, this isn't a JavaScript error. 
It's a linting error.

So I'm actually going to add   this to my package dot JSON. And all of my linting 
config is right here. So I'm going to add this as   a rule here. And say no console. Try to remember, 
this is just for demo purposes. If I were actually   building an application, I would probably want to 
have a warning or an error there, just so I would   remember to remove all of those extra console 
dot logs. Anyways, it's running now. So I'm   going to check it out in the browser. Of course, 
nothing is different right now. But if I look in   the console, may refresh. And I'm actually getting 
a promise back, which is good, it means I'm   getting the data back. But we can't see it right 
now. Because I have to update my promise chain.   So let me go back to the code.

And app file, I'm 
just going to return this turn response dot JSON.   And I'm going to change in chain another dot then. 
So I'll just say it's JSON data. And let me wrap   this, this so it's more clear. And then here is 
actually where I want to be able to access the   data from my application. So I'm going to create 
doesn't look like I have a data method yet. So I'm   going to create a data function and add a comma. 
And I'm going to return an object, oops, object.   Now, if you notice, this is a little bit different 
from how we did it in the browser. The reason this   is different has to do with some more complex 
features of JavaScript.

So we're not going to   talk about those. But it's basically required when 
you're making this type of single page application   with a bunch of different components that instead 
of just making a data object, you return an object   from within the data function. So it's a minor 
change. So here, I want to add a questions array,   which will be empty at first, and can be populated 
from the questions from the API. So here,   I don't need to return anything. But I want to set 
the questions, this questions array to equal the   questions we get back from the API.

So I'm going 
to set this dot questions equal to the data we   get back from the API dot results. Because if 
you remember, the API gives us back two things.   It gives us a response code, and then a results 
array. And the results array is where all 10 of   the questions we are pulling back are located. 
I can save this, I am still running all test it   in the browser, and you can't see it yet. So to 
inspect the data on our components, we actually   need something called Vue JS dev tools. So if you 
google view, Dev Tools, this is the GitHub repo,   if you scroll down, you can see they have 
a Chrome extension, a Firefox extension,   which I'm using Firefox right now, if you're using 
something else, or you just want a standalone app,   that's fine, too.

They all have pretty much 
the same functionality. So I already have   it installed. And it comes up on my dev tools as 
view. One of the things I love about view is that   it has all its dev tools in one place, we're gonna 
get into view x and different things later. Some   other libraries, you have different dev tools for 
different things that you're doing. So under app,   I can see all of the components imported into 
app, the child components, I can also click on   app and I can see any data variables associated 
with that component. Under questions I can see,   we have all 10 questions that we pulled from the 
API. And it's in the same format that the API   showed us with the incorrect answers, and then the 
single correct answer by itself. So the next step   here is to display the question to the screen. 
So let's go back to our code.

I'm back in the app   component. And I'm want to be able to display the 
question from this question box component. So I'm   going to have to pass it from the app component 
to that one. And I want to pass just the question   that we're on. So as you're clicking next through 
questions, I just want the question box component   to know about the current question. So I'm 
going to keep in index of the question here,   which We'll start at zero. And then view 
lets me pass data variables and methods to   my child components by using v bind with custom 
attributes. So I can say, the question I want to   pass equals my questions array and the index. So 
just the current question that we're on, and then   eventually we'll be able to click next, and this 
index will increment.

So question one, Question   two, etc. Now, if you remember the structure of 
our data, off of each question of each question.   So this is one question this object, we have the 
correct answer incorrect answer and the question,   so we have to get the question text off by using 
question. So let's do that in the question box. So   I'm going to come here. And remember the double 
mustache syntax to use variables. So I'm going   to do question which is passed from the parent 
component. And then I have to do dot question.   So maybe it would be more clear if I did. Let me 
change this to, I guess, current question.

To make   it more clear, and then I have to go and change 
it in the parent component there. So you can give   this any name, but it's going to be the same name 
in the child. But that's not the only thing. In   order for this question to display properly in the 
child component, we not only have to reference it   in the HTML, but we have to pass it through the 
JavaScript. So I'm going to create a script tag   here. And a regular ex ported object. And for 
now, I'm just going to give it the key props,   which isn't another object. And I'll put a current 
question which is also an object datatype that   I received from the parent. So any variables, 
whether it's a data property, or a method that   I'm passing from app to question, in order for it 
to display in the HTML, I have to reference it in   props and say, Hey, I'm receiving this particular 
named variable from the parent, and you reference   it the same way you would a data variable.

So 
you have your component state, which would be   local to this component in data. So this is local 
to the app dot view component. And then you can   also have props, which is any variable passed from 
another component to this component, and you use   them the exact same way in the HTML. So let's see 
if this is working. NPM, run serve again. So it   built and now let me check in my browser. There we 
go. And it's showing one of my animal questions,   zero question. I can check this. If I go down 
here into my view dev tools.

I'm inspecting   the question box component. And looking at the 
props, I see, I get the current question object,   which has the question a carnivorous animal eat 
flesh, the same thing we're seeing on the screen.   And if I go to my app component, I can look at my 
index, which is zero. So if I edit this and say,   one, then it actually changes the question 
that I'm passing to the question box component,   because now it's at the first index instead of at 
the zero index. So if I go back to question box,   you can see the question is changed. So let's 
set up the navigation between questions this   next button without having to go into the view dev 
tools to change the index.

Back in my app dot view   component, after data, I'm going to create 
another object called methods. And in here,   I want a method to increment my index value to so 
I can navigate through the questions. So I'm going   to call it next. As a function. This is basically 
a shorthand syntax for having a key of next and a   value as a function. But I can just write it like 
this in JavaScript. And in here, the only thing I   want to do right now is take The index, which 
I can refer to as this dot index in my method,   and increment it by one. So this dot index plus 
plus, and that will take the current value of   this index and data and add one to it every time 
the next method is called. So I'm also going to   want to pass the next method into the question 
box. So the same way I did with current question,   I'm going to pass in the next function, and then 
go to question box and receive it here.

In my next   button, I'm going to spread this out, I'm going 
to add an app click method, and then call the   next function on click. And of course, down here, 
I have to receive that prop. So I'll say next,   which is also a function. So now when I click 
the Next button, it should increment the value   by one by calling the next function in app dot 
view, and then app dot view should pass down the   next question in the list. So let's see if this 
works. View is still running. And let me go to the   browser. So I have my zero index right now. And 
something's not working correctly. It says current   question is undefined at question box.

So let 
me go in here and see it's still at index zero,   of course, because we're getting an error. 
And here, I have the next function and current   question. So everything looks okay in our data. 
And I think we're not quite getting the best error   message. So I'm going to check in another browser, 
copy this, go to Chrome. And now I can check in   the Chrome Dev Tools. And here it's saying cannot 
read property question of undefined. So let's go   to the question box component and see what it's 
talking about. Oops. is in question box. It says,   cannot read property question of undefined. So 
that means current question is undefined. But   when we look at the dev tools, it's defined.

So 
that means for a brief moment, when this component   is mounting, it's still waiting for the data to 
come from this component. And we can see that I'm   just going to add a lifecycle hook here. And I'm 
just going to console dot log, this dot current   question, Ben back in the browser, I'm gonna 
refresh this. And it's undefined. But in the dev   tools, it is defined. So that means right when the 
component mounts, it's still undefined. And it's a   moment later when the questions come back from 
the server, and it goes into the state in this   component, and then it gets passed to the question 
box component. So an easy thing to do would be not   to render the question box component until these 
questions are defined. So wait until we fetch the   questions and save them in the component state 
until we render this component. So I'm going to   add a V if directive. And I'm going to say V if 
questions dot length.

So if the array is empty,   then the length will be zero, which is a false e 
value. So the question box won't render. But as   soon as the questions come back from the server, 
the question length will not be equal to zero.   And so question dot length will be truthy. And 
question box will render. So let's see if this   fixes the error. Refresh. Let me go to the 
console. And now there's no error. Of course,   we're still getting our lock.

But it fixed 
the error, because now for the brief moment   in time question box is not rendering without the 
data available to it. And now we're able to also   navigate between questions, just as we would 
expect, with the next function incrementing   the index. Of course, there are still problems 
because when the index gets to 10, it'll throw   an error because that's past the length of the 
questions right, and we'll fix that in a minute.   Back in the question box component, let's add the 
list of answers here instead of the dummy text. So   if you remember our data's Structure had a list of 
the three incorrect answers and then the correct   one separately. So to display all four answers, we 
just need to put the four answers together. So as   a temporary solution, let's use a computed method. 
So I have an object of computed methods. And I'm   going to call it answers. So I basically have to 
take current question from props, and the array   of incorrect answers.

And I'm actually going to 
assign this to a new array, I'm going to say let   answers equal question that incorrect answers. And 
what I'm doing here is making a copy of the array   instead of referencing the same array. And now I'm 
going to need to take answers this answers array,   and append or push the correct answer onto the 
end. So take current question that correct answer   and push that onto the array. And of course, this 
is the array that I want to return. So I'll just   return that. So I should have all four of my 
answers in this array now. And for right now, I   will just replace it in here with a V four.

So I'm 
going to do V for vehicles and answer in answers,   which is going to reference our computed answers. 
And here, it's going to complain, because for any   V for loop, I'm going to need a key attribute. So 
view requires this for accessing these elements in   the DOM. So I can do a V bind key. And usually, 
you want to do something unique. Here, we kind   of know all of the answer, or each answer is 
going to be unique.

So each paragraph tag that is   created in this for loop is going to have a unique 
key, which will be equal to the answer. Usually,   if you're doing this in an actual application, 
you'll want to use some kind of unique identifier,   or view also gives you the option here of 
getting the index in the array. So you could   call it index, and then use index here as your 
unique identifier. And I guess I'll just leave   it like that for now. Now, if we were to look at 
this right now, we would see four empty paragraph   tags. So I'm going to put the answer text inside 
with double curly braces. Save that now I'll test   it in the browser, go here, refresh. Looks like 
I'm getting an error. What error Am I getting?   Seems like a similar error to before getting 
current question is not defined.

Oh, so I actually   referenced current question incorrectly. If you 
look here, I'm referencing current question.   But that's assuming that it would be inaccessible 
variable, actually, because it's a prop. I need to   access it through this current question. And I'm 
going to have to do this current question correct   answer as well. So this should fix the problem. 
And actually, anytime you want to access a prop   or a data variable in another function, whether 
it's a method or computed, or anything else,   you have to do this dot the name of your variable. 
So I'll save that.

See if that fixed it. And yes,   it is fixed. These are just old aerosol refresh. 
So it is fixed. But we're getting just the numbers   of the answer and not the answer text. So there's 
actually another mistake here. And it was in how I   returned answers. So I'm going to pre push answers 
here, push the correct answer onto the array. And   now I will return answers. And that should fix the 
problem. Yep. And now we're getting the correct   looping through our answers. And they're all 
for displaying if we go to the next next next,   and is displaying all their answers. Now, we 
actually want this to look a bit more like a list   and also make it clickable for the users. So I'm 
going to go to View bootstrap again. components,   bootstrap view. And I'm going to go down to should 
be a list group. Here's it, here it is. And we   want to display it like this. This will make it 
easy for a user to hover and click on an element.   So this is pretty easy.

I'm just going to copy 
this list group here. Since this is exactly what   I want it to look like. Go back to my code and 
I'm going to paste the list group in here. These,   tab them over. And I'll get rid of all except one. 
Now I want the list group on the outside, and I   want to loop through and make a bunch of these 
items. I'm going to put this on another line, put   this over format at nice. And now I can copy paste 
the loop before loop, and also copy this and then   put the answer inside instead of the dummy text. 
And that should work. Let me save that and see   how it looks in the browser, go here. And it works 
just fine. So I don't really like how the buttons   and everything rubbing up against each other and 
then up against the answers. So if I look in my   dev tools, I can refer to these with the class 
list group or list group item. So I'm going to   copy this class, go back to the application and 
just add a style tag to the bottom.

Any view   component can have a style tag in it. And there 
are different options you can use for styling.   I'm just going to use default CSS. You can also 
use sass, if you want to. I'm also going to denote   that these styles are scoped, meaning they won't 
be global styles, they will only affect styling in   this component. And I'm going to paste the class 
that I copied and say that for the list group,   I want to have a margin, let's say margin, bottom 
of 15 pixels. Save that, see how it looks. And   there's a little bit of padding. Now for the 
buttons, I'm going to put a sideways margin,   and I'm going to reference these as btn from the 
button class. So I'll put margin, I'll just make   the top and bottom zero, and then left and right. 
Maybe I'll give it five pixels. Save that. Now it   looks a little bit better spaced out. So now 
to make the buttons clickable. Let's go back   to the question box component. And I want to add 
an add click function here.

So at click equals a   new function, I'm going to create called select 
answer. And I'm actually going to pass it the   index of the answer that was selected. And I'll 
go down and create this function under methods   an object and selected answer. And then I'm just 
going to log out the index here. Let me test this   in the browser. See if it works. And it does. 
So I have the correct index of the answer I'm   selecting, the next thing is to save the Select 
index on the component. So I'm going to create a   function here and return an object of our data 
variables. And the first one, I'm going to say   is selected index. And for right now just set it 
to null. And now down here in the selected index   method, I'm going to say this dot selected index 
equals index. And we can see this in the view dev   tools.

Go back to the browser. Gonna refresh, 
go to the View dev tools. And in question box,   I can see selected indexes No. Okay, so I tried 
refreshing. And let me click again. And again, and   for some reason, this state here isn't updating. 
But if I hit refresh, in my view dev tools,   then the state updates to the correct number. And 
now if I click on this first one here, and click   refresh, now the state updates to zero. So for 
some reason, the view Dev Tools aren't updating   but our function is working correctly. There are 
still a few more steps to do to be able to get   our answers working correctly. And first of all, 
there's no visual feedback to the user to let them   know to first click on an answer or that they've 
selected an answer. So let's first create a hover   style. And I'm going to go below here, copy this. 
And say list group item. Hover, hover state.

So   when the user hovers over it, I want to just 
change the background color slightly. Right now   the background on the answers is white, I believe. 
So let me change it to a shade of gray. If FFF is   white, maybe I'll do E. And see how that looks. 
Now when you hover over it, you can see that it's   a clickable item. Another thing I should add is 
changing the cursor to a pointer. And now when I   hover, I can see that I have this little clickable 
hand. Unfortunately, when I click, let me click   on Neanderthals. And I still have to refresh this. 
It's selecting the index in the data, but the user   has no feedback here as to which answer they've 
selected, or if the application is even working.   So let's fix this by adding selected classes.

Back 
in the code, I'm going to add two more classes   here. One is for a selected answer. And I'm going 
to give this background color. Let's just say blue   for right now. Background color blue, and then 
correct answer. When the answer is correct. We're   going to give it a background color of green. And 
one more when the answer is incorrect. I'll give   it a background color of red. In order to add 
these classes into the code, we're going to use   one of our data variables selected index, which 
should be set to the user selected index when they   click on an answer.

And we need to add a V bind 
property here and bind and bind a CSS class to   this. So we're going to put class equals, and then 
it's going to be an array, we're actually going to   add things to this later on. But for right now, 
I'm just going to do selected index. If it equals   index, then we're going to use a ternary. And I'm 
going to say, let's give it the class selected,   selected. And if it's not, then we'll give it just 
an empty string, no class, save this. And then in   the browser, we try selecting a class. And it's 
not quite working, when we look at the console.

If   I refresh, then it does work. Unfortunately, it's 
a really dark, ugly color. So let's just change it   to maybe a light blue, may go down selected could 
be light blue. Let's do light green, back in the   browser. Now it looks much better. And then if you 
go next? Of course, it's not clearing the answer,   which is another bug we're going to have to fix a 
second bug is that our answers aren't shuffled. So   we actually know that every fourth answer here 
is the correct one.

And then on top of that our   Submit button doesn't do anything yet. So let's 
go back to the code and fix these three things,   starting with the answer shuffling. to shuffle the 
answers. For every single time that the question   changes, I'm going to add something called a watch 
method here. It's just like computed or methods   in that it takes an object of functions. And in 
this object, I can watch for changes to my props,   it will run this function when it changes. So 
I'm actually going to give it the same name   as my current question prop. And then when the 
current question changes from the parent, it's   going to run this function where we will shuffle 
our answers every time. So the first thing I want   to do in the function is to set this that selected 
index back to no every time the question changes,   and then I want to shuffle the answers that 
shuffle answers.

And shuffle answers is going   to be another method that I create here. And 
I'm going to copy paste this answers array   I was creating there. And here, I'm going to put 
this that current question dot correct answer. So   I have them all in an array, all four answers. 
Now I could do this with a for loop and some   randomization. But there's actually a really nice 
helper library that I can use for this to help me   shuffle an array, and it's called lodash. lodash 
is a very popular JavaScript library that's full   of useful utilities that might take you a while 
to write on your own, and that are common in   many projects, like having to shuffle an array. So 
I'm going to go to the lodash. github. Right now,   we're just going to do NPM, I lodash in 
the terminal.

While that's installing,   I'm going to go back to the browser. And we're 
going to be using a function called shuffle.   In the root of the lodash GitHub repo, you can see 
that every single utility function in the lodash   library is listed here as its own file. So I can 
actually go into shuffle j s, and see exactly how   it works, what algorithm they're using for the 
shuffle. And if I wanted to, I could just borrow   this one file and any files that it imports, 
instead of importing the whole lodash library,   I think it's really nicely laid out in this 
fashion. And it's a very good learning experience,   if you want to look through some wall written 
algorithms in JavaScript.

So it should be done   installing. Let me go back to my server NPM run 
serve. Now back in my code, I'm going to add the   lodash library, I need another data property, 
where I'm going to put shuffled answers, this   is going to be an array and I'm just gonna call 
it shuffled answers. And here, I'll put this dot   shuffled answers equals now lodash. The convention 
is to import it with an underscore and then use   it instead of calling lodash dot shuffle. I would 
import it as an underscore here. And so I'm going   to do that at the top of the script file, say 
import underscore from lodash. actually get rid of   this mounted function, and I need to tell it what 
array I want shuffled, which in this case is the   answers array.

So I do have a typo here. Instead 
of saying current question, I'm saying correct   question. Just going to fix that. Now, if I look 
at the browser, then I'm going to refresh. And   let's take a look. So right now we don't have any 
shuffled answers. Let's see if when we hit next,   we actually get shuffled answers, which you can 
see bird is the first element of the array at   the zero index, in the regular answers where we're 
just appending, the correct answer onto the end.   And then in the shuffled answers, bird is the at 
the second index, so we can see shuffling works,   unfortunately, it only works as we click through 
the questions. Also, we can check and see that   selection works. And then it does reset after we 
click for the next question, which is good. Now,   how do we get it to shuffle on the first question, 
there are actually two ways we can do this. Let   me go back to the code. And the first way is 
something that you already know, we can add a   mounted lifecycle hook just like we had before. 
And then we could call this dot shuffle answers   from here.

And that would work that would shuffle 
answers on the first component mount. And then   every time after that, when the current question 
is updated in props, it would shuffle the answers,   which is fine, it gets the same functionality, 
but there's also another way that might be a   little bit better. So I'm just going to show you 
in these watch functions. Instead of making them   a function. You can make it an object And set 
some options on the object. So I'm just going   to comment this out real quick and set it to an 
object.

pexels photo 5731816

And one of the options we have is to set   immediate to true. And then we can add a handler. 
Oops, which is another function. And then inside   of this handler function, we can do the same 
things we were doing before, and it will be called   like a regular watch function. Get rid of this. 
And now let's see if it does, in fact, update   and shuffle the questions for the first question 
that is shown back in the browser, window refresh.   And then check and see if they are shuffled. And 
yes, this is great. We do have shuffled answers   now. So just to reiterate, what immediate does 
is, instead of only running this watch function,   when current question updates, it's going to also 
run it when current question first gets passed as   props.

And then every subsequent time that it 
updates, it will also run the handler function   again. Here, I'm going to update the submit 
button. And to clean it up a little bit, first,   take away this H ref that we're not going to use, 
and then put it on separate lines, because we're   going to add a couple more things here. For right 
now, if you remember, there's the V on directive,   which I can attach to events like click, so v on 
click. And then I want to run a function that I'm   going to create called Submit. Answer. And here 
I'm going to change this directive to use the   shortcut. And now let's create the function submit 
answer here. Down in our methods, submit answer,   and this will run whenever that button is 
clicked. And the first thing we want to do is   store whether or not the answer is correct. So 
I'm going to create a variable and by default,   I'm going to set it to false.

And then if the user 
got the correct answer, I'll set it to true. So if   this dot selected index equals the correct 
index, meaning they got the correct answer,   then I'm going to set is correct to true. And 
what this is, is correct variable, I need to be   able to tell the app component whether or not 
the user got it correct. And also let the app   component know that the answer was submitted. 
Because in the header, we have a counter of the   correct answers versus the total answers. And this 
information will have to come from question box   through the app component and passed as props to 
the header. So let me create a new prop from the   app. And it's going to be this dot increment. And 
I'm going to pass whether or not the user got the   answer. Correct. So is correct. And I'm going 
to go ahead and add this as a prop here.

It's   increment is going to be a function. And now from 
the parent component, I need to actually add this   function. So let me go ahead and pass it down. And 
I have to create the function in methods. Add the   increment function with the is correct Boolean. 
And here, I need to keep track of two things, the   number of total user submissions for answers, and 
also the total number that are correct. So first,   I'm going to check if it's correct. So if is 
correct, I'm going to increment a new data   variable for the number of correct. So up here in 
data, I'll go ahead and add these. So let's say   the number of correct answers set to zero and the 
number of total answers that the user has answered   also set to zero to start.

And down here, I can 
say the number of correct increment that number by   one and then the number of total, also increment 
that number by one. I forgot that this here. So   this DOT number, correct increment by one, this 
dot total increment by one. And I want to do one   more thing here. And that's pass these two values 
to the header component to use. So add it here   or use v bind and pass the number of correct. And 
also the numb total. Now in the header to receive   these props, I'm going to create the script tag, 
script and export an object with props.

And I'm   going to do props as an array this time, just to 
have both different ways. And I'm receiving the   number of correct answers from the parent as well 
as the number of total answers. And I can put them   here with double curly braces. So the number of 
correct out of the number of total. Now we changed   a lot of things. Let's look in the browser and 
see if this works. Let's see what it's complaining   about. Seems to be okay, right now. I'm gonna 
select an answer, click Submit. Click Next. Now,   I'm wondering why it's not incrementing. correct 
them total. And it seems to only be incrementing,   the number of correct. So let's look back in 
the code and see why the total number is not   incrementing.

So we have the num total as props, 
that should be fine. Let's look in app num totals   getting past your num total here. And here. I'm 
just doing total. So I'm going to put num total   and that should fix the problem. Let me refresh 
just in case. Click on and answer. Submit. And now   my num total is incrementing. Though we shouldn't 
be able to submit a question more than once.   Because right now there's nothing stopping us from 
continuously submitting, or even submitting before   we have selected anything. So really, we should 
be disabling the submit button until we make a   selection. So let's go ahead and do that. And 
I want it to set as disabled if they have not   answered the question yet. So I'm going to do v 
bind and then the HTML attribute of disabled. And   I want this to be true if they haven't answered 
the question yet. And false if they have already   answered it, and then the button will work. So I 
can use one of our data variables, selected index,   because it will be no until they've selected an 
answer.

So I'm going to say selected. index equals   No. And let's look in the browser and see if that 
works now. So it is disabled, I can't click on it   right now. But when I select an answer, it 
gets brighter, darker blue. And now when I   hover over it, you can see the hand. And now it 
selects correctly. And if I scroll up, it will   still be incrementing. Two out of seven. Great. 
Now let's work on not being able to submit the   answer multiple times like we can right now. What 
we are doing here, just checking if the selected   index is now only accounts for the case where 
the user has not answered the question yet. So   we're going to have to add another check to see if 
the question has already been answered. And if it   has then also disabled this. So I'm going to add 
another data variable called just answered and set   this equal to false. And then up here, I'm going 
to say and answered so as long as both of these   conditions are met.

And now I'm going to have 
to add these to some functions down here. In the   Submit answer function, I want to set this.is for 
this dot answered equal to true because they've   already answered the question if this function is 
running, and then in my watch handler, I also want   to reset this thought answered, as false for 
every question I think actually in the button,   I think I'm actually going to have to do 
in order here. So if it's No, they haven't   selected answer at all.

Or if it already has 
been answered in either one of these cases,   it should be disabled. Let me save that and then 
go to the browser refresh. And then see my button   is disabled. Probably not a very good color for 
disabled button. Oh, well. And now it's enabled.   And I submit, and now it's disabled again, after I 
submit, and it counted up and I got the incorrect   answer. Now, it would be kind of nice to see which 
one is the correct answer, because I know I got an   incorrect because of this counter. But I don't 
really know which one of the other three was the   correct answer, and I can't submit it again. So 
let's change that in the styles. Jumping back into   the code, let's store the correct answer.

I scroll 
down to my data, I'm going to add another variable   called correct index. I'll set that equal to null 
initially. And now when I shuffle my answers,   meaning when I get a new question, I'm going to 
store which one of the answers is correct. I'll go   down to my shuffle answers function. And I'll say 
this dot correct index equals this dot shuffled,   shuffled answers inside the shuffled answers 
array. I want to get the index of the correct   answer after it's shuffled. So I'm going 
to use the JavaScript property index of the   array.

And then I'm going to say it's the index 
of whatever the correct answer is. So I already   have the correct answer stored in this dot current 
question dot correct answer. So now this should   keep the correct answer. So we still know it, even 
though all the answers are shuffled together. So   let's see if this is working. Go to the browser 
refresh. Now look at my question box. And I have,   huh? Well, that's interesting. I must have made 
a mistake in typing this out. Let me go and check   the code and see what I did actually misspelled 
shuffled answers. I left off the s. So now I'm   going to save this, go back to the browser 
again. And it shows the correct index. Let   me go to the next question. And the correct index 
changes per question. Unfortunately, as a user,   how do I know if what I selected was correct? 
There's no way for me to know, it just moves on to   the next question.

So let's add some functionality 
and styling. So the user can see feedback that the   answer is correct or not. And in doing this, we'll 
need to make the submit button work as well. If   you remember a while back, we made these different 
CSS classes selected, correct and incorrect. And   so far, we've only used the first one. So let's 
use the other two, we show the correct answer as   green after they hit submit. And if they selected 
the incorrect answer, then that's going to turn   from light blue, blue to red. So we're actually 
going to make a dynamic class.

And here, I'm going   to put this on a separate line. So I'm going to be 
adding some stuff, just for the time being here.   Actually, I only want this selected class to 
appear if the question is not yet answered. So   I'm going to add a not answered here and selected 
index. And just for a second, I'm going to be   nesting ternary statements here, and then I'll 
clean it up after. So right now we have the case   where it's not answered. And they've selected a 
choice. So what about if that case is not correct?   So here, I'm going to add a case if it's answered. 
And the correct index equals index. In that case,   they got it correct. We want to show it as 
correct. believe that's the name of our class   here. Yeah, correct. And otherwise, I can show it 
Has nothing. So let me save that and see how it's   working so far. Yep. So that's the correct answer. 
And now it shows the correct answer there. It says   this, there's going to be another case that we 
have to add here, after here, so I'm going to copy   this actually.

And it fits not equal to index, 
I'm going to say we're going to use the incorrect   class. Otherwise, no class. So if it's answered, 
and they didn't get the correct answer, then I   want it to turn red. So let's see if that works. 
Obviously, it didn't work that well, because every   incorrect answer is turning red. And I just want 
the user selected one to turn red. So back in the   code, I'm going to have to add one more check 
into this chain. And that will be if selected,   index equals index. And this is getting kind of 
long. And back in the browser, I mean, refresh.   There. And now it correctly shows, of course, 
this logic that I wrote is kind of out of hand.   And it's definitely messy to do all of this inside 
of a class. Just to clean this up. We're going to   move all of all of these nested ternary E's into a 
method. And we'll call that method. Answer class.   And we'll pass it the index, each list group item 
that's created.

So each answer is going to call   this method in order to see what class it's going 
to have. So I'll go down to methods and add this   one on to the end. And answer class, it's going 
to be past the index of the answer. And then,   just for reference, these are all the nested 
Turner's I had up there. I'm going to copy the   first one. And first I need to create a variable 
called answer class. And set that equal to an   empty string of an if statement. So if it's not 
answered, but they've selected an answer, then   I'm going to set answer class equal to selected. 
And I'll just change some offsets here. And if   it's answered, and they got the, or the answer 
is the correct answer, then in the class for that   particular answer is going to be correct.

And then 
a final case is if the user answered the question,   but they got it incorrect, and we want to make 
that red with the incorrect class. So it would   be answer class equals incorrect. And then down 
here, I'm going to return as answer class. Let   me clean this up. And let's see if that still 
works. Yes, so the answered is not defined. And   that's because again, I forgot to put this 
dot answered. So remember, in the template,   you can use any of these variables. But if you're 
referencing them in the JavaScript, you have to   reference them as this.so, this correct answer, 
this dot answered, and this dot selected index   and this correct index. So this is kind of long. 
I'm gonna put this on a few lines.

And that should   work. So let me try it in the browser again. 
seems to be working. It's selected correctly.   Now I can submit, and I got it wrong. So it's red 
and green. Try one more question. Submit. Yep,   it works perfectly our counter still working. This 
is the whole quiz application. The GitHub code   will be linked below if you want to take a look. 
And you can see that there are different branches   so you could look at different parts of the 
tutorial in different stages. If you wanted to.   Now we're going to build an app that's slightly 
more complicated to demonstrate how view routing   and view x, which is view state management 
system work, it's going to be a basic four screen   application.

Its theme is getting cats and dogs to 
be adopted. And we're going to be performing basic   CRUD operations to get used to state management. 
Now, there's a homescreen, two screens,   one for cats and one for dogs. And then you can 
click on any animal name, either cat or dog,   and it will load a screen just for that animal. So 
here in the terminal, I'm going to create another   view application using view create that I'm going 
to call it, adopt pets. If you remember last time,   we use the default boilerplate. This time, 
we're going to manually select features to   manually select, you can go up and down with the 
arrow keys, and press spacebar, such as here, I   want to select router.

So I press spacebar. I also 
want view x. If I wanted to use SAS or something,   I would select this one. And then I think I'm 
going to leave testing out of this particular   application. So that's all I want. I'm going 
to hit Enter. And then it asked me a few other   questions. History mode for router is literally 
a one line change in the router. And I'm going to   show you how that works later.

For right now I'm 
just going to put Yes, I'm going to pick SAS since   it's the most popular CSS preprocessor. And I want 
to show you how I include it my applications. For   this, I'm just gonna put standard config, although 
prettier, and Airbnb have some nice features as   well. Either way, all of these are just templates 
and starting points. So you can always modify any   rules that any of these set for you, I'm just 
gonna have it run linting every time I save a   file, and this is a personal preference of mine, I 
like to have my configuration in their own files,   such as my unit testing, config, Babel config, or 
my es lint file by itself instead of cluttering   up the package dot JSON that can get pretty 
unwieldy.

Now, if I want to save it as a preset   for future projects, I can click I can type y and 
it's going to ask me to give it a name, I'm just   going to type no here, and then show you the one 
I already have. And now it takes a few minutes to   build the project. Great, it's done installing. 
I'm going to go into IE adopt pets directory and   open this in VS code. This is very similar to the 
project last time still have the index dot HTML in   public. A few differences here are that in the 
main j s. Instead of only rendering the app we're   setting our store for view x as well as our view 
router configuration in our view options. Another   difference is you'll notice that here we have a 
views directory and a components directory. Now,   if you look in the router, you'll notice 
that home and about which are the two routes   are both views.

So these are the pages of your 
applications which are connected to the router,   and components are imported into the views 
or into each other. So if I look in home,   I can see it's importing the Hello World component 
hello world dot view. And it's displaying it to   the DOM. The idea is that components are reusable 
pieces. And each page stands alone as a distinct   view in your application. Now if I go back to the 
router, there's a lot of things you can do such   as lazy loading, or even using multiple components 
here. But I'm going to keep it simple for now. So   I'm going to take this out of here and import.

And 
now I can set component to just about and get rid   of all these comments. And now it's and it renders 
exactly the same. It's just a bit easier to read   right now. Now the store I'm just going to give 
a quick overview. And I'll go in deeper, you're   basically creating a new view x store, which is 
a global object. So any functions or variables,   data, anything that you want to use maybe in 
multiple parts of your application. You can store   them all here, and then import them into whatever 
component you want. And it's like a global object   for your application. The first thing I want to 
do in this app is create the four pages and link   them together. If I look in views I have about 
at home, I'm going to go ahead and leave the   home component and delete the about one And then 
create one called cats dot view, dogs dot view.   And the other one I'm just going to call pet dot 
view.

And I'll put a boilerplate template here.   And I'll do the same thing for dogs. put just a 
template here, and one for the pet page. And I'm   going to hook these up to the router. Now I've 
defined all four routes that I'm going to use   in this application, I'm going to update my app 
file to link to all four of those pages instead   of just home and about duplicate those.

And now 
put cats, dogs and the pet page, which eventually   is going to be linked through these two pages. 
But I'll just leave it for now. Dogs and cats.   And let's see how that looks. Okay, it has all 
of the links here can go to the different pages,   I'm just going to add this pipe in between. Copy 
this. There looks much better. Now let me get   rid of all this extra stuff on that page, which 
is in the home component, importing HelloWorld.   And using this image, I'm just going to get rid 
of both of these.

And just say home. Get rid of   this. And this. And now I'll delete the Hello 
World component. Perfect. Now just like before,   I want to import view bootstrap to help do 
the styling for me and lay out the pages,   we're going to go to the browser to bootstrap. 
Get started and install it with NPM. Start my   server and NPM I bootstrap view. Now back in 
my browser, I can copy the import in view.us.   And I'll put it in my main.js file. I'll put it 
up here with my other library imports. And since   I don't have a section for view.us, I'll put it 
right there. Now I need to import the CSS as well.   So I'll go and grab these links. And put them 
here. And that's it. Now that I'm importing view   bootstrap, I'm going to use some of their table 
components to display the tables of cats and dogs.   So if I scroll down here, see they have a table. 
And this table looks fine to me.

So I'm going to   copy this big table and save it and go back to my 
code and include some of these. Now let me start   with cats. And here I'm going to add that table 
component. And now of course I need the data.   So I'll add a script tag to close it and export 
default, this object data function and return an   object. And now back in the browser and see I 
need an array of objects, which I already have   in another file. And I'm just going to copy paste 
that into my application. So I'll create another   folder in source And I'm just going to call it 
data. And in data, I'm going to make two files,   one file, cats dot j, s. And the other one will 
be dogs, dot j s. And I'm going to copy and   paste data that I already have here. Here are my 
dogs. This is an array of dogs. So I'll do export   default, this array, and I have some different 
information and metadata about the dogs.

And make   close this one. And now I'll add my cats, which is 
also a very similar array. I'm going to add them   here. And now back in my cat stop view, I'm going 
to import cats from at data, slash cats. Now,   this app symbol is a shortcut that view COI sets 
up for you. And it's a reference to the source   directory. So that way, you don't have to do 
things like dot dot slash dot dot slash dot, dot   and whatnot. So I'm just going to use the shortcut 
at. And now I'm going to return cats here. So this   is the same if you don't know the shortcut, this 
is the same as setting a cat value equal to this   cats array that we're importing. But the shorthand 
is just to do it like this, since they both have   the same name. So now for items, I'm going to 
say, cats here. And I'll see how that looks in the   browser.

Back in Firefox, if I go to adopt pets, 
and refresh, I must have stopped my server. Let   me look back at I turn, and yes, I did. So let me 
run NPM, run serve again. Great. Now my browser.   Alright, it's working. And now I have a cat's 
table showing all of my cats, I'm just going   to clean this up a little bit. So it doesn't 
go all the way to the edges of the page here.   And I'm going to add a B container in my app dot 
view.

So for this router link, I'm going to wrap   it in B container, which is another bootstrap 
component provided by view bootstrap. And they'll   go back to the browser, refresh. And that looks 
much better. As far as the width, I also need a   page title. So let me create that real quick. Back 
in cats, I'm going to have an h1 here. And say   this is just cats for adoption. Alright, that's 
good. Not too fancy, but looks fine. Now I'm   going to copy paste this and do the same thing for 
the dogs tab. And I'll go back here. Go to dogs,   I'm going to copy paste this table and the script 
tag. And then I just need to change it to dogs.   Oops. Hear as well and hear. Great, so those 
two pages are looking good. Just to finish up   the homepage, I'm going to change this to an h1 as 
well.

And I'm going to say adopt a new best friend   h1. So that's all of the nitty gritty out of the 
way. Now if I go back to my browser, you can see   that I have these three pages. But this page is 
supposed to be that of an individual cat or dog   kind of like seeing his individual profile. So 
if I go to cats, for example, then the pet page   should be something like cat slash one for the ID 
of that cat. So let's learn how to do this through   the view router. View router has something called 
dynamic route matching. What it does, instead of   hard coding the whole route, you actually have 
dine namic route variable as part of the route,   it's preceded by a colon, and then you can call 
the variable, whatever you'd like. And then you   can access this variable when you go to that route 
in the component associated with the route on the   route params object. So let's see what this 
would look like in our pet component.

First,   I'm going to update the router. And say here under 
pets, I'm going to change it to be plural pets,   and slash ID for the pet ID. And I'm going to 
leave these as they are for right now. Now,   let me get rid of the link in the app dot view 
file to pets, let me just get rid of that. And now   we need our table components to have links to the 
pets page for every item. So we'll have to update   this table. Since right now it's kind of a black 
box. And we're passing in this array of cats to a   third party bootstrap component. So let's go to 
the bootstrap docs and see how we can turn each   cat in the table into a link to that page.

I'll go 
to the browser. And I'm still under the bootstrap   component tables. This whole page is pretty big. 
So I've skipped down to this format our callback.   And basically, what it allows you to do is pass in 
a template with a dynamic href. So let's copy this   and go back to the code. I'm going to expand 
this, close it here and put this inside. Now   I want to mention something about slots, because 
you're probably going to see this a lot in view,   especially if you are using third party 
libraries like view bootstrap, or if you are   creating your own components for someone else 
to use. Now, in bootstraps B table component,   it's going to look something like my format or 
doesn't like this very much.

So it's going to look   like template and then have something exactly 
like what we have with maybe a div inside. And   it's going to have a bunch of other tags, and 
it will have this somewhere slot. So bootstrap   is basically telling the component where to put 
things that we pass in to the this B table. So   it has different slots inside. And if it has 
multiple slots, which in this case, it does,   it will say name equals name, which will be a 
dynamic, because we have lots of different columns   that could vary in the table. So bootstrap will 
have a slot for each of our columns. And that's   how we can pass it in here. If you want to know 
more about slots, they're pretty easy. And they're   described really well in the view documentation. 
And here, I'm just going to replace this with   slash pets slash Variable Data dot value. And I'm 
going to change this to a router link, not using   a tag to router link and a forgotten link here do 
link you can use an a tag, I think it's a little   better and more consistent to use a router link. 
So let me go to the browser and refresh.

And now   I have links for all of these. Now, I don't really 
want it to have the pet's name, I want the ID. So   let me go back and change it. And instead of data 
dot value, which will give me the name of the pet,   I'm going to do data dot index, which will give 
me the index of the row in the array. So let me go   back to the browser and try this. And now if I let 
me go home. Now if I go and hover over it, I can   see the link gives me the index. And if I go here, 
you can see in the URL, I have pet slash zero,   which is the ID of the pet in the array.

So now I 
want to populate this page with the details on the   individual pet. So what I could do is take these 
pets arrays and import them into my pet component,   and then get the index off of the router variable 
and just look in the array in this component. But   I'm actually going to put all of the pets, dogs 
and cats in state and then pull the pet I want   from state. So let me go to the store. And this is 
a very small project. So I don't need to do this   but I just want to show you how I generally set 
this up. I make a new folder called store and in   store, I make a separate file for everything. 
So I have a file for State DOT j s, and one   for you tations dot j, s, and then one for actions 
dot j s. And now I'll make an index file to tie   these together, index dot j s. And I'm going to 
take what's in store right now.

Take all of this,   copy it, put it in the index file. And now I'm 
going to import the other three files. So import   state, from state port, he tations from mutations, 
import actions from actions. And now I can use the   shortcut here. And here, oops, this object and 
get rid of that. And now of course, I need these   to be actual objects in each file. I'll just for 
some of these export a blank object for now. Same   thing in mutations save the save this. And now 
in state, I'll have a blank object. But I'm also   going to be importing the cat and dog data. So I'm 
going to import cats from a directory data slash   cats. And I'll do the same thing for dogs. Oops 
dogs, and dogs. And now on state now this object   is the default state of my application. So it's 
the data that I'm going to be able to pull into   any component that I want. So for right now, I 
will have these separate, I'm going to do cats   and dogs as separate arrays on my state.

And now 
what I can do with this is go into my cat stop   view. And instead of importing cats from here, I'm 
actually going to import something from view x,   called map state. From view x, and down here, I'm 
going to use a computed object computed. And the   syntax for map state is to use a spread operator 
and call the function and pass it an array of the   items on state you would like to be able to access 
from this component. So here, I want to access   cats from state. So I won't actually need this in 
my data anymore. And I'm going to get rid of it.   So now I can get it directly from my view x store, 
I'll get this array. So let me go to the browser,   make sure that's working. Go home refresh. Now, 
let me go to cats. And it's not working. So I   must have an error.

Let me see what error I have 
none here. Let me go to the terminal. Now that   looks good. So let's check the dev tools and see 
if we have a problem with our data there. And in   my view, Dev Tools, I can see cats is undefined. 
So let me see why it's undefined. If I go to my   VS code, it seems like I am mapping the state 
correctly from UX.

So let me look and see if   it's in the view x dev tools, maybe view x. And 
in my base state, I don't have anything in my   base state. So let me see why nothing is in my 
state. If I go back to VS code, so I'm pulling   in the store from here. So I think the only thing 
I'll have to do here is just delete this old file,   because now it should look at the relative path 
store, which is now a directory. And since I'm   not specifying a file, it's going to look for 
the index.js file. And I'm exporting as default   the store from there. So let me go back to the 
browser. Refresh. Great, now it's working and I'm   getting the appropriate pets. So now I'm going to 
do the same thing for dogs.

So I'm going to take   this actually the whole computed here and go to 
dogs. And I'm going to add that computed object   here. And I also need map state to connect the 
view x state from the store to this component. And   I'm going to map dogs here. And I'll get rid of 
dogs in data. Perfect. So now how do I figure out   whether it's a dog or a cat in the pet component, 
I could set this up a few different ways.

But for   right now, I'm just going to put slash cat's here. 
And I'm going to turn this into another variable.   And because this isn't in my dogs component, I'm 
going to copy all of this and come back to dogs.   Instead of the end here, I think I missed the 
template. Oh, yeah, that's actually important.   So I'll come back to this. And I'm going to close 
the table here. And I just need to change this   to dogs. Now in my router, I'm going to have to 
change this to store this species. And then the Id   let me just make sure that's working back in the 
browser. Now. If I click on one of these, it takes   me to the species and then the ID. And now I can 
access these from my component. So back in my pet   component, I'm going to say this start route, 
actually, because of in the template, I don't   need this.

So I'll just say route dot, I believe 
it's params dot species, and then duplicate this   row. And Id. Let me see if that works. So back 
in Firefox, and it does work as a species and   the ID. Now quick way for me to get to the right 
cat in this component is to pull in the cats and   dogs from state because this component is its own 
view, and is not connected to cats or dogs. So I'm   going to copy the script tag here, and then modify 
it. I have map state, which I want. And I'm going   to add dogs here.

So I can listen to cats and 
dogs from here. And I just want to mention real   quick that you could do this same thing by saying 
cats, adding as a method here, and then returning   something like this dot store, dot State DOT cats. 
And this is actually the same thing as doing map   state here. But you're never going to see this in 
an application. This is pretty much the standard   syntax. It's shorthand. And it's easier to do, 
because sometimes you have a lot of elements on   state.

And it's much easier to just use the map 
state method. And now I have access to these in   my DOM. So what I want to do is find out if it's 
a cat or a dog, and then display the information   here. So I'm going to make a method for this real 
quick. Methods object. I'm going to call it pet,   pet. And inside of pet, I'm going to check for 
first this species. So I'm going to say that   animals equals Actually, I need this here, this 
dot route dot params dot species. And now this   will either return cats or dogs. And so I want 
to access it on my this object. So I'm actually   going to pass it in as a variable. If this is 
confusing to you, then it's the exact same thing   as accessing these arrays off of state.

So I could 
do this cat or this dot dogs. But I can also use   the bracket syntax and pass in a variable here. So 
I could pass in this cats, which is exactly what   I'm doing right here. Get rid of that. And now I 
have my animals here. And on my animals, I want to   see which animal I want to display. I'm just using 
an index right now. So it's easy. If I was using   an ID, then I would have to search through the 
array and find the animal with the correct ID. So   for right now, I suppose I'll just say animal, and 
then pass the index of the animal which will be   route.params.id. So I can do this.route.params.id 
here. And that should get the correct animal. And   now I'm going to return that animal and I should 
be able to use it in my DOM. So let me see if this   works. And instead of all of this, I'm just going 
to have animal dot name. Go back to my browser,   see if I don't have any errors, but I do.

Oh, 
yes, property or method, animal is not defined,   of course, because I called it the wrong thing. 
So the method is called pet. So I actually have   to get rid of animal here. And I'm calling it pet. 
And then I'm returning animal from here. So this   should return the correct animals name. And let 
me check it back out in the browser. And great.   So now, if I click on, let's say, kick cat, 
it shows up with the correct name. Of course,   this is a little bit messy. And I don't want to 
be calling the method every single time I want a   property off of this animal. So what I can do is 
in data, I can put animal and set it equal to an   empty object. And then here, instead of methods, 
what I could do is put a lifecycle method here.   So I can say, for example, when the component is 
mounted, get rid of this.

And now I can set this   dot animal equal to animal, which will set 
animal on my data object, and then appear,   I will be able to access animal dot name. And let 
me wrap animal dot name in an h1. Let me close my   h1. And I'm going to add the animals age here as 
well. So animal that age, close the p tag. And I   think I have a breed property. So let me just add 
that one real quick, too. So animal that breed.   Now I'll go back to the browser. Awesome. So these 
are old errors, I can just ignore them. Now I have   the name of my pet the age in years, and then the 
breed. And this works if I have dogs as well. Now,   I could probably put something to denote whether 
it's a cat or a dog here.

So I think I should   take this species. And I'm going to add that in 
here. And I'll put it inside parentheses. And   then I also want a label for the animals age. So 
here's old. And for breed, I'm going to put this,   I should have this year to four age, I can put 
here and that should look a lot nicer. And now   when I go here, I can see I have labels on these. 
And I can now see if it's a cat or a dog. Great.   So another thing we probably want to do is be 
able to edit these animals to add CRUD operations.   And that will lead into how to use actions and 
mutations in the store. So let's jump back into   view x. Let's start by adding the functionality 
to be able to add a pet. To do this, we're going   to have to append the new pet to the array in 
store to one of the arrays.

Now the pattern that   you'll generally see for doing this is definitely 
not updating state directly. Because that's what   mutations are for mutations are there to update 
state for you. And generally speaking, you will   call it an action that calls a mutation, which 
update state. And a lot of the time the actions   that you call will be where you're also making API 
calls because they're asynchronous. So we're just   going to use that pattern of using actions that 
call mutations that update state. So in actions,   I'm going to add an add pet method. And view gives 
me a context object here. And then I can use an   argument when I call this function. I'm just going 
to call that pet for right now. make this an arrow   function. And with context here, it has a couple 
MIT method on it.

So I can use commit. And this   will call a mutation for me. So I'm going to need 
to create a new mutation. And I'm going to call   it append, pet. And I'm going to append that 
pet with my new pet object that's going to be   passed into this function. I want to make a note 
here that this is generally not how you will see   this being used.

Because context, you only need 
the commit method off of it. So you can actually   pull that directly off the object here. And this 
is generally how you will see commit being used.   And remember, this object comes from view x. And 
this pet is the custom parameter that we're going   to be passing into the function. Now I'm going to 
copy this name, append pet, and go into mutations.   And I'm going to add a mutation called append 
pet. Here, again, we have two parameters. So the   first that view x gives us is state. So we have 
the application state. And then the second is   whatever payload we're passing into this function. 
So that would be pet here. And I'm going to make   this an arrow function again. And from here, we 
can mutate or update state. So I'm going to say,   so State DOT whatever species, which is an 
array, so I can actually push the new pet onto   that array.

To do this, of course, I'm going to 
have to pass species into this with pet. So here,   I'm going to change this so that I'm passing in an 
object with pet, and also the species of the pet.   So for shorthand, and because I'm just passing 
this straight through, I'm just going to call it   my payload, which will have payload dot pet and 
payload dot species. And I can pass this payload   directly into my append pet mutation. And from 
here, I can D structure this and say, species,   and pet and state that species, which will be 
cat or dog, and I'll push the new pet onto that.   And that should append to either our cats or dogs 
arrays. So I'm going to do this for cats and dogs   at the same time. So I'm going to go to home and 
add a button here with a bootstrap class of btn.   And I think btn primary to give it some color, I'm 
going to say add new pet, and this should toggle   and add new pet form.

And now in my JavaScript, 
I'm going to add a methods object and say,   toggle pet form. And this dot pet form equals 
the opposite of this pet form. And of course,   this is going to be a Boolean. So I also need 
to add data method and return an object of my   data variables. And one of them, of course, 
will be pet form, maybe to be more explicit,   I should say, Show pet form. So it's obvious 
that it's a Boolean. And to start off with,   I don't want to show this pet form. So I'm 
going to say it's false. And then every time   that this method is called, it will toggle the 
form from showing. So now we actually need the   form. And for that, I'm going to copy of view 
bootstrap form. And I'm just going to take this   most basic form at the top and then modify it. So 
I'll come down here and copy everything in B form   up b form. And now back to the code, going to add 
that form here.

That looks good. And I have to of   course, update all of these functions because 
it's not going to run right now. So get rid of   at reset, which I'm not going to use now show 
pet form. So it will show this pet form if this   variable is true. So this button will toggle it. 
And I'm going to make a handle submit function   for when the user submits this form which will 
have Eventually call our action.

Right here,   I'll add the handle submit function. And for right 
now it's not going to do anything. So let me just   fix the rest of my form real quick. We want the 
pet's name. First and foremost, we don't need   an email address for the pet. So I'll get rid 
of that one. And now this example input group,   I'm going to say pet's name.

And for the drop 
down, I'm going to say, species. And for options,   it will just be an array of cats and dogs to 
choose from. And that should give me a good   drop down menu. I'll add one more form group here, 
copy this one, and overwrite the check boxes. And   I'll say pets age, enter age here. And type will 
be a number. Now here, of course, all of these v   models I need to update. So I'm going to make 
a new data variable here, I'm going to call it   form data. And it's going to be an object that's 
going to model all of my different form inputs. So   I'm going to have form data dot name, which will 
start as an empty string. And I'll just give age   a default of zero for right now.

And species, I'm 
going to say is no. And let me update these here.   So form dot age, formed that species and name 
is fine. So also need to update this to form   data instead of just form form data and one more 
form data. So our form should be functional all   the way until submit right now, let me just try it 
in the browser, I have the add new pet button. And   it's not toggling the form. So let's see in the 
Vue JS dev tools, in app in the home component,   show pet form, doesn't switch to true ever. So let 
me say true here. And it does show the pet form.   Now I know where the errors happening, I go back 
to my code, I can see that this toggle pet form is   never being called. Because I forgot to add it to 
the button. So I'm just going to do an add click   here.

Say toggle pet form. That should work back 
in the browser, refresh. And now it toggles on and   off. Great. Let's hook up the submit button. In 
the JavaScript here, I'm going to import another   view x helper called map actions. And this works 
in the same way as map state. To do this, we need   to add map actions to methods. Now the reason why 
we add the actions to the methods and the state   to computed is that we are watching for changes to 
state. And we're not watching for changes to these   static methods. They're just functions for us 
to call so that we can get state updated. So now   I'm going to pass in an array. And my action was 
called add pet. So I'm mapping that to my methods.   And now I'm going to call it from handle Submit. 
And I can do that by just saying this dot add pet   and then passing it the payload. So the payload 
is an object that I'm going to create here. So   const payload equals this object, and the payload 
should have the species and then it will have a   pet object with things like the name and age.

Now 
to get this information. I'm going to pull it off   of data here. So the form data object. And I can 
do that by using this syntax. When a pull species   age and name off of this that form data and put 
this in the wrong spot. So Click this outside of   that object. And now here I should be getting all 
of my right information, passing it as an object   with species and pet as the payload. And then this 
will go into the actions here as my custom payload   that I'm passing through to a mutation. And the 
mutation will have species and pet pulled off   payload. So I can update state cats or State DOT 
dogs and push the new pet. Let me see if this is   working in the browser. refresh this add pet, 
add Bosco, and is a cat Smit, okay. So if you   notice the page refresh here is pretty quick. 
But it's not actually going to submit the form   correctly because of that refresh. It's handling 
it in the default way when it's supposed to be   submitting a form to a server. But of course, 
that's not the functionality that we want.

So   I'm going to come back here, go to home. And now 
for our submit handler, I'm just going to add   that prevent. And if you remember, this modifier 
is just like calling event dot prevent default,   just like you would in a regular function submit 
handler. But this is a shortcut that view has. So   I'm going to come back to the browser. And now 
if I add a new pet, cat, the age is 22. And I'm   going to submit this. And I think it's submitted 
correctly. But of course, we're not clearing out   the form after so there's no feedback, whether or 
not it's submitted.

So let's go to cats, and we   see a cat is appended to the table. Awesome. Now 
I just want to clean it up a bit and clear out the   form when I'm done. I'm gonna see, no, it's clear 
now. But I wanted to clear right after I submit to   give some user feedback. So if I come down here, 
I'm going to add something to reset the form after   Submit. So I'm gonna say that this start form 
data equals an object. And I'm going to reset   it to exactly what it was before. These. Okay, 
now, let me try to submit another pet. This time,   I'm going to submit a dog 12. Submit. And now it's 
resetting the form after it's submitted. And let   me go to dogs here. And it correctly added the 
dog. Of course, there's a lot of other things we   could add. But that's basically how view x works 
is that you'll call an action from a component   and actions are asynchronous. And then from the 
action whenever you're done doing what you want   to do with the action, you call a mutation, and 
then the mutation update state, and then whatever   components are listening to state, because 
you're mapping the state to a computed function,   those components will update in the DOM, where 
it's needed.

Now I want to show you real quick   how getters work. There is actually another object 
that goes into the store. And it's called getters.   So getters are like computed properties. But for 
your view x store, what does that mean? Perhaps   you want to pull state into a component, but you 
want to modify what the component receives while   you're pulling it. So it won't actually update 
state, but it will get back something that you   want out of state. For example, we could count how 
many animals we have in our arrays in a getter,   and then call that getter from everywhere, we 
want to get the number of animals. So let's just   create that real quick. I need to first create a 
getters object and a getters file. And it's the   same as the other view x objects. I'm going to 
export default in object here, and I'm going to   call it animals count, which is a function and 
here I'm going to have access to the state and   I can do whatever I want with the state before I 
return it to a component, another arrow function,   and if I want to get the total count of 
both cats and dogs, I could say something   like state that Cats dot length plus state that 
dogs dot length.

And now, to use these getters,   I need to put it in one of my components. So I'm 
actually going to put this in the home component.   And I'm going to put it just above the button. So 
I'm going to say, animals count here. Of course,   I need to map this. So there's another method 
called map getters. And I need this inside the   computed, because we're watching for changes on 
this. So I'll put map getters here.

And this is   using the spread operator as well. So that's a 
method with an array, the same format, and that   will be animals count, let me make sure I got that 
right. Animals count animals count perfect. Let's   see if that works in the browser, if I go home, 
and I see I have eight, which is exactly how many   animals I have, because I have four cats and four 
dogs. But of course, pulling this from a getter   didn't update state at all, is just modifying 
how state is seen by a component. So I can run   whatever function I want.

Now, one common thing 
that you'll be using getters for is for filtering,   so I can say something like get all cats. Now, 
to do this, I'm going to need to create another,   we're going to need to create another array here. 
And this time, I'm going to call it pets. So   instead of cats and dogs in separate arrays, I'm 
going to give it one array, cats and dogs. If you   haven't seen this syntax before, it's basically so 
that the array is flat, because if I just put cats   and dogs without the three dots behind each, it 
would come out being all of the cats in one array,   and then all of the dogs in another nested 
array.

So this is an easy and nice way to   make all of the pets together in one array. 
So now that all of the pets are together here,   I'm going to need to add what species they are 
inside the data to differentiate between the two.   So I'm going to add species is cat. I'm going 
to copy this and just paste it in all of these.   one extra. And I would put this in dogs too. But 
just to show the getter example, I'm going to say   get all cats will be return State DOT pets, which 
will have both cats and dogs in it. And then dot   filter, the filter method takes a function, 
which will give us each pet one at a time,   and allow us to return just the pets we want in 
an array. So I'm only going to include the pets   in the array where pet sees me pet that species 
equals cat.

And now I should be able to use this   get all cats getter? Well, once I add state from 
my component, and I'm going to do that here. So   I'm going to say add another variable, get all 
cats. And I don't want to print out all of those   objects. So I'm just going to put length to see 
how many cats is returned. And of course, I need   to add that inside my getters.

Get all cats. And 
now I should be able to call this from the DOM   and check how many cats are returned versus the 
total number of pets. Back in the browser. I see   it's getting the correct number of cats versus all 
pets. In case you can't see, there are four cats   and eight total pets. That's basically how getters 
work do used a lot for filtering or making changes   to what's going to be rendered on the DOM. You 
can do a lot of different things with getters, you   could also pass in other getters. So here I could 
actually call another getter inside this getter,   because view x gives me that as a second argument. 
This whole system is pretty simple. Once you've   practiced it a little bit Another thing that I 
think would be helpful in a production application   or as you're building your personal projects, 
that is setting up SAS inside of a project. And   this is how I generally do it in view. So I add a 
folder inside of source slash assets called sass.   And then I have an index dot sass file.

And I make 
a couple folders inside of my sass directory. So   I have my components, and my libraries, and my 
global styles, which I usually call base. And   then I import all of these files into my index. 
So I'll import first libraries, and then base.   And then I'll import components here. So inside 
of the libraries folder, I might have mixins,   or material design or whatever other sass files I 
want to import here. I can also import CSS files,   I just renamed them dot s CSS, because any valid 
CSS can also be used inside of dot SCSS files,   which is a type of sass file. I just prefer 
to use invented syntax without curly braces,   or semi colons. And there are some extra shortcuts 
that you get with the indented syntax that I like.   So after the libraries, the base files, I'll 
generally have something called variables,   dot SAS.

And now this underscore is just a 
convention in SAS to mean that this file is   imported into another file and not compiled as an 
individual file. So I have a variables file. And   here I might do something like, set my fonts as 
a variable. So I could set let's say, main font.   And set that equal to I'm not sure how vedika 
if that's right, or whatever, Google Font that   I've imported, or any other font, and then sans 
serif.

And do colors and padding and spacing,   I'm just going to do maybe a blue color here, 
which could be 000034. And then you get the idea,   you can put pretty much anything you want to be 
able to use in other parts of your application,   and then you can just change it in one place. 
And this also makes it easy. If you're doing   different themes, or letting a user choose their 
theme and their application, you just save all the   different themes here and then attach them to a 
class and toggle that class dynamically from the   JavaScript inside your view components. 
So now that I have some variables here,   I can import this into my main sass file. And 
within at import, I'll say base slash variables,   and I don't need the underscore or the dot SAS on 
the end, it's going to look for either dot SAS or   dot SCSS files.

And I think this makes the file 
look really clean, it's easy to look through a   whole list of these. Now in the components, 
let me just pull up one component here,   let's say a view and my home view. And it starts 
out with the class home. But generally, I don't   think this is descriptive enough. So I usually 
call things like home view container or something   like that in my project. And this is a wrapper 
class so that I can contain my nested classes, and   they don't affect other parts of the application. 
Because my global styles will all be in base.

But   each component that I make will also have its 
own styles. So I'm going to create a new style   file for the home component. And then I put this 
wrapper class, and then any other classes that I   want to affect the home component I'll put nested 
inside of here, just so you can see the nesting,   I'll put four spaces instead of two, which is 
generally what I use whenever I'm doing something   like Python or SAS using indented syntax, because 
it makes the indentation easier to see. So now I'm   just going to say color and use my color variable 
that I'm also importing into my index file.

So now   in components, I will add import, base slash home 
Now I have styles that are specific only to the   home component. So how do we get these styles to 
apply to the components, you have to import them   into the main.js file. So right below where I 
have these bootstrap files imported, I'm also   going to import from the assets folder, sass, and 
index that sass. And now, that should apply all   of my sass files to my project. Because if you 
remember, when we created this project from the   vcli, we chose sass as the preprocessor. So the 
vcli, set up all of the sass processing for us,   and being able to compile it to CSS and things 
like that, which makes it really easy to use sass   inside of projects.

So it's complaining about this 
app import statement. So let me add components   here. And now it's working fine of the the text 
is not turning blue. Let me see why that is,   if I go to inspect element, it is actually blue. 
But it's just so hard to tell, because it's not   a very bright color. So let me change that to 
a brighter color. If I go into the variables,   and I'm just going to change this to any color, 
not necessarily blue, just so it shows up.

I have   no idea what color this is okay, purple. And it 
doesn't affect any other page here. Because I   am using a namespace in sass. So it only affects 
anything inside of this class, which is specific   to the div wrapper around home dot view. So 
hopefully that makes sense. I do make usually   one of these components for every single of my 
component files. And then in global styles, I'll   put inside various styles in the base directory. 
So that's enough about sass, I just wanted to show   you how I usually set up a sass project. This 
code will all be online, if you want to see it,   I want to change one more thing that feels a 
little bit dirty about this project. And that is   to pull this table out into its own component. In 
my components, I'm just going to create a new file   called pet table dot view.

And I'm going to use 
this as a table inside both cats and dogs. So to   start this, I'm going to just steal this template, 
put it here. And to make it unique for each one,   we're going to need to pass in some props to this 
component from both our cats and dogs views. So   I need to have props are my default object. I'm 
going to make this an object and say first of all,   I think we're going to need a species, which 
will be a string. And then here, I can replace   this with species. It's gonna be lowercase. And 
here I'll replace this with pets because we'll   pass either cats or dogs as pets.

And pets will be 
in array. And then here I also want to use species   to dynamically pass. And I think that's it really, 
we just have to import pets table. Let's import it   into cats first. So import pets, or pet table. 
From at components slash pivot table dot view,   and I need to set it as a component I'm going 
to use my Dom here, components pet table.   Not sure if I mentioned this previously in the 
video, but using pet table as a component here,   I can do this in two different ways.

I'm going to 
get rid of this and I can use it capitalised or   view gives me another default way to do it. Which 
is kebab case by default to make it more HTML like   I could do that. Generally the recommended way 
that I've heard from members of the core team   and others and also from using it myself, is to 
just keep it capitalized. And that lets you see   the difference between the custom components that 
you create and the other HTML tags like div So I'm   going to be passing in this species here. And 
I know the species is cats. So I don't have to   do anything else to that. And I'm also calling for 
the pets or the cats, which I need to pass in.

And   I have that array here, mapped through computed. 
So I'm going to pass that in using v bind as pets   pass in the cats array. Of course, this is kind 
of confusing, because these have the same name.   But this one is an array because we're using v 
bind. So view is looking for a variable. So it's   actually pulling this variable cats array off of 
computed and sending it in as pets. Now species,   we're not using v bind here, so it's just static. 
So it's the string cats. And let's see how this   works. If we go to the browser, and go to cats, 
it's still working the same way.

So I'm going   to copy this for dogs. Go here, into the dogs 
component, and get rid of all this table stuff   here. except we're going to be passing dogs in 
for both of these. And then we need to pull in   the pet table component from here and also add 
that component so that we can use it in the DOM.   And I'm going to add it here. And then it should 
work still for both cats and dogs refresh.

And   it works for dogs just as well. And we can still 
see that we have the correct number of both being   pulled in. So that's all for this view tutorial. 
If you're interested in going further with view,   let me know and I might make a more advanced intro 
to view in the future. Here are the resources   I think are most helpful for getting into view. 
First, there's the state of uJs, which is a yearly   report put out by ovenu, who's the creator of 
view, he gives lots of great talks about how the   project and library are evolving every year.

And 
you can find those for free on YouTube. Another   resource I highly recommend is somebody who's the 
senior view developer called the Jared Wilker,   he livestreams. Various tutorials mostly about 
view every Thursday night at 7pm. Eastern time   in the USA. He's a really great teacher. So I 
highly recommend jumping into some of those chats   and asking him questions. Then there's one of my 
favorite people on the Vue JS core team, Sarah   dresner. Now I didn't cover animations in this 
tutorial, but she's actually the best person to   talk about those types of things. Vue JS has a lot 
of great built in animation features. I'm going to   link a video of a talk she gave on view animations 
that I think is really good. One last thing I   recommend for getting into view is checking out 
the views on view podcast. You can find it on   dev chat TV, or on overcast or any of your other 
favorite podcasting applications. Thanks so much   for watching this whole tutorial. I know it's kind 
of long, but I hope you got something out of it.   If you have any questions or feedback from me.

You 
can find me on Twitter at Gwen underscore Faraday,   or shoot me an email at Gwen faraday@pm.me. I 
also have a YouTube channel called coding with   Gwen that I'm going to be starting back up here 
soon. And this is kind of a kickoff video for   that. So if you are interested in more of these 
types of videos, you can check me out there thanks.

You May Also Like