Learn Vue.js - Full Course for Beginners - 2019

Learn Vue.js - Full Course for Beginners - 2019

SUBTITLE'S INFO:

Language: English

Type: Human

Number of phrases: 1244

Number of words: 27205

Number of symbols: 105885

DOWNLOAD SUBTITLES:

DOWNLOAD AUDIO AND VIDEO:

SUBTITLES:

Subtitles prepared by human
00:00
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,  
01:01
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  
02:07
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,  
03:07
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  
04:10
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.  
05:24
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  
06:27
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  
07:34
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,  
08:35
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  
09:43
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  
10:48
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  
11:53
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  
12:58
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  
14:03
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,  
15:14
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,  
16:17
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  
17:30
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,  
18:37
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  
19:38
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  
20:40
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,  
21:40
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  
22:47
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  
23:49
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  
24:56
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  
26:00
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,  
27:09
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,  
28:22
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  
29:24
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  
30:25
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  
31:29
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,  
32:40
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  
33:44
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  
34:52
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.  
35:58
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  
37:07
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  
38:14
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  
39:18
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  
40:20
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  
41:27
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  
42:34
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  
43:39
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  
44:43
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  
45:54
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  
46:55
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  
47:57
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  
49:01
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.  
50:05
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  
51:07
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  
52:11
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  
53:11
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,  
54:17
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  
55:25
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  
56:29
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,  
57:36
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,  
58:37
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  
59:38
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.  
01:00:51
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  
01:01:53
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  
01:03:02
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,  
01:04:06
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  
01:05:13
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  
01:06:18
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  
01:07:23
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  
01:08:24
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  
01:09:24
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  
01:10:31
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,  
01:11:35
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  
01:12:37
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,  
01:13:42
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  
01:14:44
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  
01:15:46
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,  
01:16:49
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  
01:17:52
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  
01:18:59
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  
01:20:02
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  
01:21:04
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  
01:22:10
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  
01:23:13
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  
01:24:17
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  
01:25:28
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  
01:26:33
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  
01:27:36
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  
01:28:44
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  
01:29:49
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. 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  
01:30:54
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,  
01:32:02
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  
01:33:08
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  
01:34:13
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  
01:35:23
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,  
01:36:26
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  
01:37:29
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  
01:38:32
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  
01:39:44
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  
01:40:52
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  
01:41:54
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,  
01:43:04
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  
01:44:11
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  
01:45:18
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.  
01:46:27
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  
01:47:31
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  
01:48:39
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,  
01:49:40
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,  
01:50:48
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  
01:51:51
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  
01:53:01
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  
01:54:08
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.  
01:55:13
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  
01:56:14
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.  
01:57:14
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.  
01:58:20
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  
01:59:22
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  
02:00:28
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  
02:01:34
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  
02:02:42
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.  
02:03:53
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  
02:04:56
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  
02:05:58
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  
02:07:07
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  
02:08:17
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  
02:09:20
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,  
02:10:26
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  
02:11:28
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,  
02:12:32
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  
02:13:38
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  
02:14:39
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.  
02:15:40
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  
02:16:52
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  
02:18:02
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  
02:19:04
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  
02:20:06
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,  
02:21:13
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  
02:22:17
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  
02:23:26
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  
02:24:29
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  
02:25:33
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  
02:26:37
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  
02:27:42
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,  
02:28:49
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  
02:29:55
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  
02:30:55
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  
02:31:59
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  
02:33:02
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  
02:34:09
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  
02:35:10
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  
02:36:17
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  
02:37:17
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,  
02:38:18
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  
02:39:27
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,  
02:40:29
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,  
02:41:41
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.  
02:42:54
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  
02:43:58
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  
02:45:04
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,  
02:46:10
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  
02:47:16
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,  
02:48:22
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  
02:49:23
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  
02:50:30
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  
02:51:33
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  
02:52:39
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  
02:53:46
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  
02:54:52
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  
02:55:58
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  
02:57:03
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  
02:58:09
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

DOWNLOAD SUBTITLES: