Gwendolyn Farraday previously created one of
the most popular Vue courses on the internet. Now she's back with an all new full Vue course to
teach the latest version to absolute beginners. Hi, everyone. My name is Gwendolyn
Faraday and I will be your instructor for this course. I have been a professional
software developer for over five years now. And I've had the opportunity to work in several
different languages and frameworks over the years, including Angular react, and Vue js. I
currently work as a software consultant in various technologies, and use Vue js as my
preferred front end framework for any type of web or mobile application. If you would
like to reach out to me, you can find me anywhere online at Faraday Academy. If you
have any specific feedback for this course, please email me at gwenf@protonmail.com.
I hope you enjoy this course. Vue js is a JavaScript framework for building
applications and websites. How does it help you? It provides tools out of the box to help you make
your websites and apps faster and more dynamic. And it also gives you a set of standards for code
organization and expectations for individuals and teams that work in the same code base. If
you have heard of the virtual Dom before, Vue js is a virtual Dom framework. If you don't
know what that is, it's okay. It's not important for understanding this course. The virtual Dom
basically makes JavaScript web applications a little bit faster and more efficient
Vue by itself is extremely lightweight, you can get it down to about eight or 10 kilobytes
g zipped. Although in a practical sense, your Vue and bundled JavaScript will probably never be that
small in an application anyway. Although it is good to know that Vue doesn't have a lot of extra
code taking up more space in your application. Why does Vue JS call itself a progressive
framework, they use the term progressive to mean that you can use it anywhere from
small features on websites where you want to add some interactivity and using it as
kind of a drop in replacement for jQuery and legacy applications. All the way up to using
it as a more full featured batteries included framework for large scale applications like
Gmail or Twitter or something like that. You get to decide what features you want to add
in from the Vue ecosystem beyond the core library, and it's extremely flexible to allow you to
choose the tools and other libraries you want on your own. Or you can use the ones that
Vue provides in its ecosystem by default, many people and companies are using it for its
incrementally adoptable nature. That means that if they have a legacy application, it's quite
simple to update their application page by page to turn it into a Vue application into a more
modern application, instead of having to rewrite the whole app at once. That is one very convenient
thing about Vue j s. Let's look at a really quick overVue of the history of Vue. The Vue project was
started in 2013 by its founder, Evan you. In 2014. version one launched and started to become popular
in China where revenue is from a few years later, Vue two was launched with many new updates
and improvements over Vue version one. And with the release of version two is really where
we start to see the massive growth of Vue j s and popularity in the rest of the world. So many
developers had not heard of uJs before 2017. But from 2017, and especially in 2018 and
2019 Vue really solidified itself as one of the top three JavaScript frameworks. Many Vue
conferences started popping up lots of content creation around the Vue ecosystem started to
take place. And many companies started to use Vue for their applications as well. In fact,
many companies that do you recognize, which are household names in the West, use Vue, j
s now. And now we can see that Vue version three has been released in fall of 2020. And along
the way, over these last six years, we see many different libraries that are also created and
maintained by Ave and the core team of Vue. Like the vcli Vue router in Vue x, also being regularly
updated to match with the current version of Vue. Even now, with Vue three just released, we
see that a new version of Vue, router and VX have also been released to be compatible with
Vue version three. In this course, we will be using the Vue j s core library as well as the
vcli. For more information on Vue, x Vue router, Vue test utils and some of the other tools in the
Vue ecosystem that I don't cover in depth in this course, I will be making future courses about
those on my Faraday Academy YouTube channel. So let's get started with learning v j,
s. And keep in mind, I'm using v3 here. So make sure you are at the correct
website, which is v3 dot Vue, J s.org. And then click on getting started here. This will
take you to the documentation. And by default, the introduction to Vue j s, I'm going to go straight
to the installation link on the sidebar here. And if I scroll down, I can see the place where
it says CDN. And you'll notice here it says Vue add next make sure you are importing the
right library from the right URL here at next is necessary, because Vue three is not
in the main Vue j s repository yet it's in this other repository that you can reference
with that next, which points to Vue three, until the whole ecosystem and everything finishes
getting updated. There is going to be a difference between importing Vue to an importing Vue
at next, which points to Vue version three. And I'm going to go ahead and grab this script
tag here. So I'm in VS code, and I just have a basic HTML file. And I'll be adding Vue
j s into this application to demonstrate the basics of Vue syntax before I get into
building a larger application with the Vue COI. So first of all, I'm going to be using VS code
plug in called live server. And you can see at the bottom here it says go live. So if you go to
plugins, which is this four box icon on the side, you can type in live server and click on this plug
in. And you can install it if you do not already have it installed. But I already have it installed
and enabled. So I'm going to go back to my code over here. And at the bottom, I'll just click go
live. And you can see it shows my HTML page, I'll just zoom in a little bit here with the static
content. Now if you don't want to use live server, you can just come here and right click and click
on copy path. And then you can go to your browser and paste that absolute path to the project
or to your index dot HTML file. And it will display the same way in the browser. live server
just makes things a bit easier because it will automatically refresh when you make code changes.
And it also opens up the browser page for you. But it's up to you if you want to use it or not.
So now I want to add Vue to this application. So I'm going to go inside of the
body tag and just below this div, just paste in the script tag that I just copied.
So now this is all that I have to do to import Vue and start using it in my application. I
don't actually need Babel or anything else to get started. So to write my own custom code,
I'm going to add my own script tag right below that. So there's basically two things that I
need to do here. And the first is to use this Vue variable that I have access to from importing
Vue. And that script tag and Vue gives me this method called create app. And that basically
creates my Vue application. And I can pass it an options object, which I'll get to in a second.
Now I need to somehow connect this JavaScript for my Vue application with the HTML that I'm going to
be displaying in the browser. And that is through another method that I can actually chain on to
this Vue instance I'm creating. So I'm actually going to save this as a variable. I'm going
to say let app equals Vue create app. And then I'm going to use this other method called
Mount because I want to tell it to mount my Vue application somewhere in my HTML here.
So I'll do ID equals, I'll just call it app. And I'm actually going to tell it to mount
to my Vue j s application inside of that div. And that means that the Vue j s instance that I'm
creating here will be able to connect and display data and interact with any kind of DOM element
inside of this div here. So that will be more clear in a second. So now let me change this,
let me create a variable on my Vue instance. And to do this, I need to create a function called
data here. Now this whole object here is called the options object. So any variables or functions
that I'm going to use in my application will live on this object here. So specifically with data
that is a function, and it needs to return an object. And on this object that is returned by
the data function, I can put whatever variables I want. So I'm going to create a greeting variable.
And I'm basically going to say hello, v3, then exclamation point. And now I
can actually go into my div here, delete that static code there. And I'm going to
use my variable now. So to use a variable in Vue, you use this double curly brace syntax, it's
called double mustache syntax, which is kind of hard to pronounce. So you can just call it double
curly braces. It's a common syntax in templating languages. And it basically means that anything
found in between these sets of double curly braces will be parsed as JavaScript by Vue. So Vue is
first going to look inside of this data object that we're returning, and see if there is
a variable named greeting, and then it is going to display that variable or the value
of that variable inside of these curly braces. And you can see that now it displays the
greeting variable from our Vue instance. Let's talk about Vue j. s directives. They are
basically a way to connect elements in our HTML or template here with the Vue j. s JavaScript. And
let's see what that looks like through an example. I'm going to create an input here.
In the browser, it looks like this. Now, what if I want to get the value out of this
input Vue has a built in way to do that through a directive called v model. Now, these directives in
Vue are used just like an HTML attribute, but they are prepended with v dash to differentiate them
from regular HTML attributes. And Vue when it is parsing this Vue application will see this keyword
v model, and will bind it to whatever variable we pass in as an argument to the model here. So
here inside quotes, I need to put a variable name. And I'm actually going to put the variable
greeting here. And let's see what that does. So you can see now in my input, it actually starts
off with the text Hello Vue. And as I change it, it also changes the greeting variable that is
displayed on the page. This is called two way data binding and is handled in Vue with that V
model directive. Let's look at another directive. I'm going to create an HR here. And I'll make
a div with a class of box. And I'm going to use another directive here called v if, which also
takes an argument, which will be another variable. So I'm going to set an is visible variable
which I have to create. So let me do is visible and set this to true to start, I am going to
paste in some styling that I made. This is just to style the box so you can see it on the page.
Awful that you can see that I do see that box, because this V if directive is basically just
like an if statement in JavaScript. So if this value is truthy, then this element will be
displayed on the page. But if it's false, this div will not be rendered to the DOM at
all. So let me change this variable to false. And you can see the box disappears. And if I
check, I can inspect element. And there is no div found in the DOM. Now v If is very similar
to V show, which is another vj s directive, it takes the same kind of argument a Boolean
expression. And let me set this to true again, you can see if it's true, it
shows on the page, just like v if. However, when it's false, you can see there's
still a div, render to the DOM. The only difference is the style is set to display none.
So you won't actually see it, but it is there in the DOM. So when would you use v show? Well, in
most cases, you would just use v if, because you either want something to render or not. Like if
you have a loading spinner, you would use V, if it's loading show the spinner. And then
when the page or whatever has loaded, you would set the variable to false and then
v if would remove it from the DOM. Now v show is useful for specific cases, when you might
need to toggle something more frequently. And it would be more performant than adding and removing
it to the DOM constantly. So it's already there, all you're doing is changing the CSS. So you're
changing it from display none to display block. So changing this back to Vf. There are other
directives that you can chain on to Vf. There's v, elsif, and V else. And you can already guess what
these do. So I'm just going to show you the syntax here. So v else if and V else is the one that
doesn't take any argument. And I'm just going to demonstrate these really quickly. I'll add another
variable here. So it's visible is visible to. So I've added a little bit more CSS here to
differentiate between the three boxes that I've created here. And this works as a regular if
else statement. So if is visible is true, this div will be rendered. If it's not true, it's going
to keep going down the chain. So it will look at any v else ifs you have here, you can have as many
as you want. So then it will look at is visible to to see if that is true. If that's not true, then
it will automatically display this third box. Now the third box is blue, the second
box is red, and the first box is purple. So you can see the blue box displayed
because the other two values were false. Likewise, I could change one of these
variables to true. And then that box would be rendered in the DOM here. Now I want to
point something out here, if I refresh the page, you can see for a split second, you
actually saw all of the boxes render, as well as the curly braces show up on the screen
here before it was parsed as a Vue variable. I'm going to refresh the page again and slow it down
a little bit, just in case you couldn't see that. So how do I prevent that from happening? Vue has
something called v cloak, which is a convenient utility that will hide anything from rendering
until the whole Vue application is ready. So I'm going to add a V cloak here. And then I
basically need to add a style for it. So you can see, I'm setting v cloak or this V cloak attribute
to display none. This is the recommended pattern in Vue js. And then I just add a V cloak to my
div with my app in it. Now if I go back here and refresh, you no longer see the curly braces
or the other boxes render. How does that happen? I'm going to go to inspect element. And you
can see on the div with ID app here, there is no v cloak attribute. But if I refresh the
page, you can't really see it because it's too fast. But basically, that V cloak attribute
remains on this div until the app is loaded, and then it's removed. Once everything is rendered
to the DOM. I don't often run into cases where I have to manually use this, but it is a nice
feature to know about if you run into that issue. These were just a few basic directives. We
will definitely be covering more directives as we go along in this course. In the next video,
we will go over events and methods in Vue js. Now that you've seen how to use variables and
directives in Vue, j s, let's make this code a little bit more interactive with a So you probably
already know that there are many events that can be captured in the browser and used in our
applications. For example, when the user clicks on an element on the screen, like a button, or if
the user presses a certain key on the keyboard, like Enter to submit a form, let's try out both of
these cases in our little mini application here. First, going to get rid of the two extra
boxes. And I'm going to add a button here. Which for right now, I will label as showbox.
So right now, this V if is set to false or the variable is visible set to false. So this div will
never be rendered on page unless we somehow update that variable. Before we were hard coding the
variable value here as true or false. But we can actually use this button to change the variable
value as well. And this is done with another directive called v dash on. Now, the v dash on
directive is specific for events. You can use it for custom events that you create yourself. Or you
can use it for any of the standard browser events, like, as I mentioned before, when a user
clicks or presses a key on their keyboard. So here's specifically, I'm going to do v on
colon, and then the type of event which will be a click event. So I'm listening for
a click event on this button right now. But now when someone clicks on the button, I have
to tell you what to do with that click event. So I need to pass in an argument of whatever JavaScript
I want to run when this button is clicked. And for right now, I will keep it simple. And
I'm going to set the is visible variable to true when that button is clicked. Now you
can see I have this button show box. When it's clicked, the box shows what if I want
to hide the box. Right now, this only shows the box. And the only way to get rid of it is by
refreshing. I can set up a toggle for the box, by simply saying is visible equals the
opposite of whatever it currently is. So is visible equals not as visible. So if it's
true, it will be set to false. If it's false, it will be set to true. And this should
toggle our box, we label this to toggle box. And now, if I keep clicking toggles on and off,
that is basically how events work. There's also a shorthand for creating events. So you don't have
to type out the dash on colon, you can just type the app symbol, and then the event name. And this
is exactly the same thing as it was when I typed v dash on colon. the at symbol just replaces all
of that. So what if you wanted to do something more complex in here not just setting a variable
to True or false? Well, you can actually use this to pass in any kind of method on your VJs object.
So I'm going to get rid of is visible here. And I'm going to create a method called toggle
box. And now I have to create this toggle box method. You can see I already have data on my vj s
object, this data function. But now I need to make another key, which is called methods and
methods is an object of functions. I can put as many functions as I want on this methods
object to be able to use these in my Vue, j s application. So let me create that toggle
box function. I could do the same thing here as I did above, but I'm just going to use the
function shorthand and I want the same logic again but inside this function, so in order
to refer to this is visible variable here, I have to get it off of the this context. And
Vue j s handles putting all of my methods and variables on the this context so that they're
available to me anywhere in my Vue application. So I can do this.is visible and then set it equal
to not this.is visible This is not function there. And this should work the same way as it did
before. So I can test it out and toggle the box once again. So that is the basics of how methods
work. And you can see because I have called my method toggle box That it is also available
to me anywhere inside my Vue JS template here. So let's look at one more type of event.
And that will be an event listening for keyboard input. So here I want to listen for key
presses. This is also an event. So I'm going to start with the Add symbol. And listen for a key up
event. I could also use key down if I wanted to. So for keyboard events, I need to add a modifier
to say which keyboard input I am listening for. So for input here, I want to run a function or some
JavaScript, whenever I press the enter key. So for enter, I actually have a shorthand because this is
a common keyboard input. So I can say, Listen for the key up event specifically with the enter key.
Or I can always use the key code associated with any key on the keyboard. So for enter, that
would be 13. It doesn't matter which one I use, I'm just going to go ahead and use key up dot
enter, because it's a bit more obvious what it is. And then it's the same syntax here. And I'm going
to create a greet method for this key up event. So let me go down to my methods, create a method
called greet. Use the method shorthand. And I'm actually just going to console dot log, this dot
greeting. And let's see how that works. So I can just focus this input anywhere and just hit enter,
it doesn't matter what's already in the input. And you can see it logs out the
greeting. If I change the input, it logs out whatever the greeting variable
is currently set to. Now what if I want to pass something into a function as I'm calling it
into one of these methods, then I could do that, just by adding the parentheses to call the
function. So for example, greet here, I can just pass something in. So just for demonstration
purposes, I'm going to pass in the greeting through the template here. I'm going to accept
that here. And I'll still call it greeting. And then get rid of this because I'm no longer looking
for the greeting variable. On the vj s instance here, I am actually just going to be using the
greeting variable that I am passing in here. And just to show you that it's different, I can
use the greeting variable and then pass it in with some exclamation points appended to it. And
now when I go here, and I click Enter again, you can see that it is the greeting variable
that I passed in through the template. If I erase a few characters here, hit ENTER again,
you can see it's still the same variable set to the new value. Those are the basics of
how to use events and methods in Vue js. I do want to point out here, you see this dot
enter, that is an event modifier in Vue js. So you're not only listening to the key up event
you're listening to specifically the enter key. Now there are many modifiers that you can use. For
example, at this click event here, for example, I get I have a modifier here that says I'm
only listening for right clicks. So a normal left click on a mouse will not trigger this
toggle box. But only if you make a right click, I can also use some handy modifiers like
prevent. So if I don't want a form to submit instead of using the regular event dot prevent
default in my method, I can just add this modifier here dot prevent. And I can do that for stop
propagation as well. So I could add that stop. You can chain as many of these modifiers as
you want in Vue j s, there are definitely a handy thing to know about when you're building
Vue applications. That's all for this video, we will be diving deeper into events and methods
later on in this course and in future courses. In the next video, we're going to talk
about custom components in Vue js. Let's talk about Vue components. Now when
we created our Vue application here, we are basically just using one standard component, you
could call it just a default options object for use in our template. So now we're going to work on
breaking up parts of our application into separate components in order to prepare for learning how to
build larger applications and work on applications with the Vue COI outside of a single HTML
file. Let's take a break from the code for a second and take a look At what we are going to be
building with Vue components, we're going to use a simple example of a form to work on breaking
up an application into separate components. Now, where you see the red outline, those
are each going to be a separate component. So the outer red outline around the whole login
form will be its own login form component. And then each input with its label will be a
custom input component that we are going to create and be able to reuse for as many inputs as we
have. So we're going to start off with this outer component, and then break out the inner components
into their own components after that. And then we are going to look at how you can pass data
around between components in your application. So what would a Vue component look like?
Let's say we wanted to have a form in here. And I'm gonna get rid of this greeting really
quick. And put a form here. So I could do this directly in the HTML and create a form tag. Or
I can create a custom tag as a Vue component called custom form. Now, this is the same
syntax as if it were an HTML tag. Except, of course, it is not a standard HTML tag. So I
have to define it as a Vue component down here. And I need to define it after I define my
app variable, which is my Vue instance. And before I actually mount it to the
DOM, so I can chain this here as app dot component. This is a function and it takes
two arguments here that I'm going to pass in. So the first one is the name of the component
that I'm going to use. And that is the name that I'm going to be using in my HTML up there.
So I'll give it the same name custom form. And the second is an options object. And since
this is his own self contained component, I can actually use any of the same options that I've
been using here, such as data and methods, etc. The only extra thing that I need right now is
I have to define a template for this component. And the easiest way to define a template is
by using graves. So I can make this multi line and pass in the HTML here. So real quick, I'm
going to create a div. And I'm just going to put, let's say, two inputs in here for right now, but a
type of email, and then an input type of password. And let's call this a login form. Since we're
doing email and password, I'll change that up here to login form. And since template is the only
required option that I need to pass in on this object, it should run like it is right now. So
let me see if this works. I'm gonna go to go live. And you can see these two form inputs up at the
top here, completely unstyled, just basic browser inputs. So I'm going to style these inputs
really quickly, so they're easier to see. After all of these boxes, I'm going to add
a reference to input here. I'm going to say margin of 10 pixels just on all sides, and
display of block so they don't go in line. And now they are a bit easier to see here.
Alright, let me code for the styles again. And now let me add a data method to this
component. So you can see what that looks like. So after this template key I have here, I'm going
to do the same thing I did above. With data, I'll just use the function shorthand here, return
an object. And here I'm going to give it a title. And the title will be login form. And now
I need to do something with this title. So up here when I defined variables, I use them
inside of my app template here. But since my login form is a self contained component, any
variables I define on data here, I am going to have to use them inside its own template. So
I'll just add another line here and give it an h1 and by the way, This doesn't
have syntax highlighting, and isn't kind of a weird template form. Because
I'm just doing this all in one HTML file. This is just a stepping stone to get to more
standard ways of creating Vue components where you will have syntax highlighting, and auto
completion and all of those other great features. So here, I need to use that variable title.
So I'll use that the same way I did before by referencing it. And now I should see the title
on top of those two input boxes. And indeed, I do here I am, zoomed in quite a bit. So that is
a basics of how you can create a component here, I'm going to go ahead and keep building out
this form, and then also show you how to compose components now. So I'm just going to
change this really quickly to form. And then I'm going to add some submit functionality here.
So I'm going to add an event for submit, submit, and then pass in an argument with the method
I want to run or the function I want to run when I submit a form. So I'm just going to
call my function, I suppose handle Submit. And then I need to make a methods object down here
with that function. I'll call it a handle, submit. And I will just console dot log
submitted. So now when the form submits, it will run this function, there's a few
more things that I need to do, I need to add a button here, that will actually submit
the form. So by default buttons are type submit, so I don't need to add that here. But I
am going to add some text to the button. Now when the form submits it refreshes the whole
page. Of course, this is the default behavior in browsers. So you can just automatically click
and send data from the form to your back end. But since we are going to be handling the form
submission from our handle submit function, we don't want this default behavior with
the page refresh. So like we saw earlier, we have event modifiers. So we can do prevent,
to prevent default, this would be the same thing as passing in an event object to our handle submit
function, and then doing e dot prevent default. Again, this is just a shorthand. So
now if we look at our console, here, we see that it logs submitted when we submit the
form. So now, we probably want to be capturing these inputs. So we can do that. Again, by using
the directive v model to bind to the value of the form input to a variable, we'll call this one
email. And we'll v model this one as password. And then add these into data. And now let's
log those out. So let's log out email. And password. Of course, if you remember, I have
to get it off of the this context, since I'm referencing it inside of JavaScript here. And
now I should be able to type in something here, this has to be an email. So
I'll say gwen@example.com. Just any password, and I'll click
Login. And you can see it did log out my credentials here. Okay, so that's one
component. In the next video, let's look at how to break up this component and take out
the inputs to put them in separate components, as you saw in the markups earlier in this video.
And we'll also look at how to pass data between components. So from a parent component to a child,
and then also from a child backup to the parent. So what if we want to compose multiple components
together? Let's demonstrate this by removing the inputs and creating a custom component just for
our form inputs. Let's say we want some logic just contained within a special input component. So let
me fold this real quick. And I'm going to create another component here. I'll do app dot component
again. And I'm going to call this custom input passing in options. object. Again,
I need to have a template here. And in this one, I'm just
going to have Label Label when a display a label variable here, and
then I'll have that wrap around the input. And I'll use a type, just the default text
for right now we'll change that in a second. And that is a default input. So now where am I going to use this component,
so I'm actually going to replace my input fields in this component with this new one that I
created. So what I can do here is Call this Custom input, and custom input. And I can use my
components inside of this other component. Now there's one more step that I have to take
here. And that is registering the component. So I have to let my login form component
know about the other custom component. And I can do that here by creating components
array, and then just give it the string of the component that I want to be using, which is
custom input. Now let's see how this works. Okay, so I have these two inputs. Now it is giving me
this warning, that property label was accessed during render, but it's not defined on the
instance. This is happening, because here, I'm referencing this variable label, but it is not
defined anywhere. So it's giving me that warning. Now I could define data function here and
create the variable on this component. But I want to demonstrate passing data from one
component to another. So instead of defining it on this component, I'm actually going to define
label on the parent component and pass it to the custom input component. To do that, I'm going
to come here and add just a label, let me add in, we call it email label for right
now. And I'm going to call it email. And I'll also have a password, label and call this password. Now I have to get these two variables
passed into these custom components here. And so what I'm going to do here, I can go ahead
and get rid of the V model for just a second. And I'm going to add a label here that I'm going
to pass in. And I'm going to pass in the email label. Now this looks just like an HTML attribute.
But I'm actually going to add a modifier on here. That is a Vue directive called v bind. What v bind
does is basically turn this regular HTML attribute into something that can be parsed as JavaScript
so that I can pass down a variable to the child component. So I'm v binding this label, which is
email label, which refers to this string here, which is email, this will get passed down as a
property to the child component called label. And now in this custom input child component, I
need to receive that property to accept it here with a props object. And the simplest way to
write props is to make an array of strings, just like I did for custom components. And these
props are basically just a list of all of the names of the information that I'm passing down
from the parent to this child. So now, because I'm defining label in props, I will have access
to use the label variable here inside my template. Now if you look at the login form,
you can see that the email field, it has a label here, and you can tell it to
label because when I click on the word email, it focuses on the field it's related to.
So let me give a label the password now to I'm going to pass in password here. By the way
v bind, there is also a shortcut for V bind. This is one of the most common directives
in all Vue applications. So the shortcut is instead of using v bind colon, you just use
colon and then label. So let me pass a label in here as well. So I'll pass a label in As password
label, since we're using this reusable component, the label will always display as the label
that we pass in. And now you can see that both form fields are properly labeled here. Now
I want to point one thing out really quickly. And that is for email and these password
labels, you could not make variables for these and just pass them in as strings here.
So for example, if I get rid of the bind of the colon, shortcut there, then I could
just pass in, let's say, password. And let me put enter email here. So it's different.
And now I can just pass in this text as a string. Because there's no more v bind here, Vue is
no longer looking for a variable. So now in the application, you can see that it's just
passing the string down as a label to the child component and displaying that string, I'm
going to do those changes. When you're working in actual Vue applications, you will see that 95%
of the time, you want to pass a variable in when you're passing a prop down to a child component,
either a data variable or some kind of a function. So you'll almost always be using this V
bind syntax here. Now there's one issue because in the child component, we have the
input down here, we're not actually listening for changes to the text in the input, we're not
v modeling that to any variable, so we don't have access to whatever is inside the input.
So we actually need to create a V model here in the child, I'm going to save the model.
And just temporarily here, I want to map this to a variable in the child. And I'm going to could
just call this input value. And I need to create data function here, return an object with input
value as an empty string. So now in this case, you're already familiar with the model. And you
know that anytime we type a character into this input, it's going to update this variable and
this variable, and the input will stay in sync. But now how can I get the value of this
variable up to the parent component here, because I actually want it to stay in sync with
these two variables on the parent component. So that way, when I submit my form, I can have
access to it in this handle submit function. So there are actually a couple different
ways of doing this. I'm going to show you the most straightforward approach for getting
started with this. And then in future courses, I'm going to explain a little bit more in depth
about how you can use custom events and other methods of capturing the value of a variable from
the child to the parent. So to get started, here, I'm going to use my same input variable.
But I'm going to use a new object here. And this object is called computed. I'm
going to comment out data for a second. So computed is an object where you can put
variable names in here as keys. So for example, this input value variable that I want to
create, I can put it in here as a key. And whenever this value changes, I can actually
get it to run getter and setter functions. So I can create a getter function, and then
a setter. So when I get the variable value here, it will run this function. And
then when I go to set the variable value, it will run the set function. So now what value
do I want to put in my getter here, I want to get that value from the parent component. So
I'm actually going to use these two variables that I already have here. And I'm just going to
get rid of these types. I'm not using them yet. So get rid of those. And I'm actually going to
do something different. I'm going to create v model directly on my custom component here. And
I'll show you why in a second. And I want to model this to the variable that I'm going to be using.
So for this one, that is the password variable. And for this one, that's email And these got out
of order. So I'll switch them around. Okay, so now I'm be modeling the email and password. And now I
want to get these variables in my child component here. Now, how do I do that. So in props, I can
actually accept a prop called model value. And this comes from the parent. Now it doesn't really
look like we are passing in another Prop, because we're not v binding any variable and passing it to
the child. But actually, what v modeling does on a child component is actually under the hood,
it's giving us another prop called model value, which is mapped to email. So v model does a few
steps all at once, it's kind of a shorthand here. So I have access to this model value prop because
I'm using the model. So I can accept that prop in the child here v model. And then in my getter
function, I can do this dot model value. And I can return that. So now whenever I get the value for
this input, it should be the same as the value in the parent component. And I can check that by just
typing in some values here. And you can see that the inputs are pre populated with the value from
the parent component. Because I am v modeling this input to a getter function that I'm setting here
and saying that the value will be this dot model value, which comes from the V model variable in
the parent component, which are these variables. So now, how do we handle setting the value if
we type text into this input here, so we need to capture the value first and Vue passes this in
via a parameter. So we can give this parameter any name that we want, I'm just going to call it
value. And I'm just going to first log out this value. And so here, I can try typing in. And you
can see it's logging out the value of the input from that log in the setter function. But
now it's not setting a variable anywhere. So let me go ahead and set the variable. Now to
do that, I'm going to use a new method that you haven't seen yet. And that is this dot dollar
sign emit. What emit does is allow me to emit events that other components can listen to. And I
can pass data around by Vue application like that. I can emit events that are built in like I could
emit some kind of on click event or something like that. Or I can emit a custom event that I create.
For right now I'm going to use an event that Vue gives me and this is called an update event.
This syntax is actually new, slightly updated in Vue three. So if you see older tutorials,
and might not be using this exact same syntax, it will probably be using an input event here
instead. But I'm going to pass in a value here. Oops, I need a comma. So this
first argument is the type of event that I'm emitting. And the second argument is
the value that I'm passing through that event, which is this value that I'm getting
from the input via the set function. Now, how can I listen for an
event in another component? I could set this manually. But like I said
before, V model is a shorthand. So v model is actually listening for this update event from
my child. And whenever this update event emits, this V model from the parent component is
updating the value of the variable for us. Let's test this out. I'm going to start typing
here, typing here. And I'm going to press login. And you can see that it logs out the
values of the email and password. So this isn't that clear. So let me put a real email here,
or real fake email anyway. And you can see there's the email and there's a password, which are
coming from this log statement in handle Submit. Now, you might be wondering, why do we have to
go through all that trouble to model a variable from a child to a parent. And the reason why
is because the props that we pass to children, they are immutable. We cannot them
in the child, these variables on data here can only be changed in the same
component. So my custom input can't change anything we pass in via props here. So for
example, if I tried to model this to label here, getting all of these warnings attempting
to mutate prop label, props are read only. So I'm gonna undo that. So that's why I had
to create this extra variable in the child and create a getter. So I'm getting this
read only model value prop from the parent. And then what I'm doing to update the value of
that prop is I made it emitting an event to the parent, this update model value event. So the
parent, because I have this V model shorthand is listening for that event. And this
component, this login form component is actually updating these variables itself. So
I'm not actually mutating props from the child. Now, there are definitely other ways of handling
changing props in the child component, I could listen for changes on this input. And I could call
a method on a methods object, which could do the same thing either amid an event, I could also pass
a function from the parent to the child, and the child can call functions in the parent. And then
I could update variables in that way too. There are also other state management solutions. And we
will explore all of these different options later, I just wanted to give you an initial taste of how
this can be done in Vue js, and specifically in Vue version three, now that the syntax has changed
a little bit. So in this video, we've gone over custom components, composing components
together, importing them into each other, like we are with this custom input into the login
form component. We also talked about using props, passing data from the parent to the child, and
then being able to set data by emitting an event that the parent can listen to and passing it a
value. In the next video, we are going to talk about loops in Vue to simplify our syntax here
with having multiple of the same component. Now let's talk about loops. Here, we have two of
the same component, these custom input components. And I would like to just be able to loop through
as many of these components as I want. To do this, I need to add an array and data here. And
this array will have all of the information for each input here, including the variable
that I want to model to the label name. And I'm also going to add a type. So I'm going
to create an array here called inputs. And just to demonstrate really quickly, I'm going to add
just some strings here, like email, password. And let's say name. So what if I wanted to
display all three of these strings inside the template here, I'm going to come back to looping
over the form in a second. But for right now, I'm just going to create a p tag here. And I
want to show each one of these strings inside its own paragraph tag. So I'm going to create a
loop for these, I'm going to say V four equals, and then I need to pass in the array here,
which is called inputs. And this will loop over the inputs array. Now this is a four in
loop. So I'm going to have to create a variable that I can use in the iterations. So I'm
going to say for str, short for string in inputs, and now I have access to this
string variable each time through the loop. And I can basically just display it in a variable
now. Right, so it is complaining that I made a mistake in my syntax. And of course that is
because I didn't put a comma after my array. And now you can see that these top three here are
strings that are displayed in a paragraph tag. Of course, they are so big because I am zoomed in
so far, but they are displaying properly. And that is basically how you use a loop in Vue js. I am
missing a prop here that I need to add. Whenever you do a loop you have to add a key prop here and
this key has to be unique on E iteration of the loop. Now the reasons for using this key prop are
a little bit more advanced. So I'm not going to go in depth on it in this video. But I just want you
to understand that it is good practice for you to use a key that will uniquely identify any elements
that you loop through in your Vue JS templates. This can help with performance and preventing
bugs in your applications. And when you move into programming a more structured Vue application with
Vue components in their own files, you will see that your linter and code editor will pick up on
it if you don't have a key value here. And it will give you a warning and ask you to add one. So we
have to have a key to give a unique reference to each one of these paragraph tags, we're adding
into the template. Now what I can do since the names are unique here, each string is different.
So I can v bind to key, the string variable str. This is a really simple Vue application.
So you basically don't notice a difference in the browser. But you can see that there
are keys attached to these elements. Now, I want to point out though, that one more
way that you can create this unique key every time through the loop is you can actually
get an index through each iteration of the loop. You can get it here and then use it as your key.
And if I print out I, you can see that I is the index of each iteration in the loop, put that
back a string. So this was just a demonstration, of course. So I'm actually going to get rid of
this whole p tag here. And what I really want to be putting in inputs here are objects for the
information that has to do with each input that I want. So the first one, let me put a label
here. And I'm going to say the label is email, I'm going to create a value here. And this was
what I'm going to V model to. And then I'll go ahead and add a type. So let's say type is
email. And I'll do the same thing for password. I can get rid of those now. Alright, so now my
application is broken, because I got rid of all the data that I had been passing into these custom
inputs. And actually, I'm going to get rid of one of these custom inputs, because now I'm going to
be looping over just one, and it will create one for each iteration of the loop. Let me clean this
up a little bit. But these on separate lines. And so the first thing I want to do is create a
V four here. And this V four will look through inputs, just as I did before, I'm going to say
four inputs in inputs. And I'm actually going to get the index here really quick as well. And
then use a key of V bind the index. So now I can't v model email, I need to V model based off
of this input object, which is each object in this inputs array. So I'm going to have to V model
input dot value here to model it to the value. So I'll do input that value, the label, also,
I'm gonna have to do input dot label. And now I do have a type. So let me rebind a type
as well. And I'm going to do input dot type. So that's one thing that I need to
update in this child component. Now, I'm still accepting that model value prop and the
label prop. But I also want to accept a type prop now. And instead of doing type is text, now
I have a prop from the parent based off of which component it is in the loop. So now I'm
going to V bind this so it can take a variable, and I'm going to say type, which will
refer to whatever prop I've passed in. So I'm going to come to my form here. And I'm
going to type in and I actually forgot to change the logging here for handle Submit. So I don't
want to overcomplicate things for this example. So what I'm going to do is just delete this and
log out this dot inputs of zero and that value and then this dot inputs, have one and then
that value. And this should fix my problem here. Let me just type something in. And it's
complaining that I don't have an email address, I'm just going to type in a fake email, login.
And you can see that it has my correct login information. So this is the basics of how
to handle loops in Vue j s, is you can use V for either on regular HTML elements like an h1
or any custom components that you make as well. This is very commonly done with card components.
If you see a website like Pinterest, how it shows all those different little boxes with pretty
photos in them. If that was both in Vue js, it would be doing this V for loop over
all of those data objects that make up all of those Pinterest cards on your Pinterest
wall. The last thing we need to look at before we get into the demo application is lifecycle
hooks. So we will cover those in the next video. Another important concept in Vue j. s is lifecycle
hooks, also called component lifecycle hooks. So what is the hook and what are component life
cycles. To understand this, I made a quick demo. Similar to the demo that we
started off with in this course, I can click the toggle box button and a box
appears. Now I'm using a V if to take this box, add it you can see it was added
to the DOM. Now if I click again, it was completely removed from the DOM here,
that whole process of coming into the DOM. And then finally leaving the DOM. That is the
life cycle of this box component that I have. Now, sometimes things might leave the
DOM because you navigate to another page, or because something is coming into Vue via
scrolling, or because you're hiding and showing something like this example. In any case, you can
use something called lifecycle hooks. A hook is just a function that will be triggered to run at
a specific point in the lifecycle of a component. For example, it's a function that will be called
right when this purple box appears on the screen, or right before it leaves the screen. If
you look at the Vue, j s documentation. Now this is the version two documentation here,
because they don't have what I'm going to show you yet in the version three docks. But it is
the same thing. So I'm under learn guide. And then if I scroll down on the sidebar, I'm at
the Vue instance and creating a Vue instance. And I can actually click on
the lifecycle diagram here. So this is a diagram like it says of the
instance lifecycle of your Vue instance. And like it says, You don't need to fully
understand everything that goes on right now. But it is a useful reference. And this
chart isn't just useful for your Vue instance. But every single Vue component
will have access to these lifecycle hooks. So you can see these two up top in the red. All
of the boxes in the red are the lifecycle hooks, you can see before create and created, these
hooks will be run right before and right after Vue. js has initialized your component.
Now the next two before mount and mounted, the format is run right before your component
is mounted to the DOM. And mounted is run as soon as your component is mounted to the DOM.
components can also go through updates. So before update and updated, like it says here, this
will happen. Or these updates will be triggered when data changes on your component. So any
of those data variables that you create, if you're incrementing a number or changing some
kind of value, then updated and before update will run. And then when your component is going to
leave the DOM. Now here it says before destroy and destroyed. Now this terminology has been updated
for Vue three for these two lifecycle hooks. So if we go to the Vue three documentation
now and we're on lifecycle hooks here. I'm going to scroll down so you can see
before create created before mount mounted before update and updated. I'm going to
skip over some of these and Now you can see it's before unmount and unmounted, which is
in place of before destroy and destroyed. The lifecycle hooks function exactly
the same way, they've just been renamed. I hope this will become a little
bit more clear as we look at a demo. So in the code, you can see I have
the same box that we used before appear. And here is the toggle box button inside
of my Vue template. But this time, I do have a special test box custom component that I made,
which is toggled based off of a V, if so this is my main application. And the options object
with my is visible variable for whether or not the box is visible. And then I just have a toggle
box method, which I call when I click this button. So again, this is pretty much the same thing that
we did before. Except for this new component here. I put the box in its own component. Now Now that
we've learned about composing components, and I'm just going to add some lifecycle hooks here really
quickly to illustrate when these are called on the component lifecycle. So I'm just going to add
a couple of them here. We're gonna add created, and then mounted, and then unmounted. And in
each of these, I'll put a console dot log. And let's see when these console dot logs print
out. Back in my browser, I'm going to hit toggle box here. And you can see in the terminal at the
bottom, created, printed and then mounted printed in the same order that we saw in the VJs
documentation. So this one happened before. And then this one happened after it was mounted to the
screen to the DOM here. Now if I hit toggle box, again, we can see unmounted prints because
that is run after the box leaves the DOM. Now let's look at another one. After methods here,
I'm going to put lifecycle hook on this component, or on the main Vue instance that we
have here. And I'm going to try updated. And I'll hit toggle box. And you can see
that we have created and mounted those both print from the box component itself, but from the
main instance also updated prints. And that is because we are updating this data variable from
is visible false to is visible true. And so the update function is triggered on this component
because our data updated for that component. And if we toggle it again, we can see updated is
run again, because that variable was changed to false again. So updated will run every single time
the data changes. Now, why might you want to use a lifecycle hook, some of the most common use cases
are checking whether someone is authorized to Vue a certain page or component. A lot of people use
the created and mounted hooks as well to pull data into their application from a back end or from in
browser storage. Sometimes they are also used to initialize events. And then when the component is
about to unmount, you can clean up that event. Or you can save some data or run some kind of check
on before unmount or in the unmounted function. So those are the basics of lifecycle hooks, I
encourage you to test out lifecycle hooks on your different components and see what happens when you
use different lifecycle hooks. In a future course we can get into some more advanced examples and a
few of the more advanced lifecycle hooks as well that you won't see as often. So those are
the basics of Vue js. In the next video, we are going to build a Vue three application
from scratch, starting with the Vue COI this time. This is a demo of the application that we will
be building. It's a simple shop application with a few items. Now it looks like the web page is
already done. But actually it's just static HTML and CSS so far. As you can see, if I click the Add
to Cart button, nothing happens. And if I scroll up, the only things that are actually functional
on this site right now are these top nav links. Which are just regular browser anchor
tag links to bring you to another page. So this one goes to the Products page. And you can
see I have this cart, which is not functional. So if I click the X, nothing happens, it's just
fully slid out here to demo how it will look. And if I click the X, nothing happens, it doesn't
delete the item, I can't add items to the cart. And on this page, I have a past Orders table,
which is also just static content right now. This project is going to be a little bit
different than tutorials that you are used to, we are not going to be starting from scratch
with some mock ups here. Instead, we will be starting with a static application with HTML and
CSS already coded, then we will figure out step by step how to add Vue JS into the application.
This will help to give you a deeper understanding of how Vue works and how to build real world Vue
applications. First, I will give you an overVue of the code base. And then we're going to see how
it looks in the browser. And then finally, we will start with the Vue JS portion and implementing
our own Vue code into each feature one at a time, the goal is to eventually reach a point where
it gets to be difficult to continue to code inside of HTML. And then we are going to move
the project over to a Vue COI setup project where we will have Webpack and the full
ecosystem of Vue j s tooling and libraries like Vue x and Vue router. So let's get started
looking at the code. So I'm going to start here with the package dot JSON. Now this is the file
that's generated by NPM. You should have seen one of these before if you've worked with JavaScript,
and it has some metadata about our project here, and then the scripts section. So you don't need
to know what all of these scripts are doing. This code will be available for you. So if you
want to dive deeper into each one of these you can. But since we're focusing on Vue here, the
important part is that we have this start server that compiles our styles and serves
our application for us. Now later on, I'll show you how to start an application
with the vcli. But I had to use some kind of a temporary server here in the meantime.
So that's what live server is doing for us, it will serve it on a port, similar to what we
did with the live server plugin that we used in VS code for the last demo application. So to
start this application, I'm going to go up to my terminal option here. And I'm going to
choose new terminal. And my terminal opens at the bottom here inside my current folder. And
I'm going to run the start command. So NPM start, you can see that automatically opens the
application on the correct port here. And if I scroll down, I can see the same page
that you already saw. Now back in the code, let's look in the source directory. So the source
directory is where all of our JavaScript and other code is going to live. And this is where we'll
also be adding Vue js. This is our main HTML file for the application, which is the home page. And
you can see the links here go to Vues pages inside of this Vues directory over here. So the links
will take you to the past orders page and also the Products page. Now to start working with Vue
j s, I'm going to start with these cards here. Right now I want to be able to update and save the
quantities and be able to add them to the cart. So in this app dot html file, I'm going to go ahead
and add my link to Vue j s, just like I had in the last demo application. So I'm going to go
to the bottom here and paste the script tag. So I'm importing vj s. And now I need to write
some custom vj s code to get my application. So I will create another script tag. And here
I'm going to do let app equal Vue dot create app up a pass it in empty object for right now.
And then here I'm going to do app dot mount and then mounted in the same DOM
element as before with the ID of app. And let me just check here. Yes, the wrapper
div here. If I fold it, you can see all of the content is created inside of app. So to get
started here I definitely want to create a data method. And I need to return an object. And
on this object, I want to track my inventory. So when someone clicks the Add to Cart button,
I want to increment or change the amount of inventory that I have. So inventory itself will
be an object. And you can see the different types of produce that I have here. So carrots,
pineapples, and cherries. And so I'm going to add these three items to my inventory, carrots, and
I'm going to initialize all of these with zero. That looks good. Now I need to find these elements
inside my application and put the variables there. So if I look down at these cards, you can
see here's the recommended product section. So I have carrots here. And I have the price
here is the quantity with the input field. And what I want to do here,
instead of setting the value, I want to do v model. And this
should be inventory, dot carrots. And then I'm going to copy the same thing for the
other fields. So come down here to pineapples, and paste this. And then cherries as well. Okay,
now let me take a look at that. And you can see it still shows zero here. Just like before
I can update a number, we do three carats. And now the number starts at three. So now we want
to do something when someone clicks add to cart, if they have a certain quantity in
here, we want to add it to a cart total, we change this back to zero. So to do that, I need
to create a method, we create my methods object, I'll create an Add To Cart method. And in this
method, I need to take in the number of items that someone wants to add to their cart, and also
the type of item. So to do this, I'm going to need another place to store what
items are actually in the cart. So I'm going to create a cart here. And for right
now, I'm just going to copy the same items over. And then when I call the add to cart method,
I need to pass in the type of item and quantity, then I can access my cart variables
by doing this, that cart and pass in a variable that I want to access on my cart object, I
need to use the square brackets, and then I can pass in type. So it would be the same as
this cart carrots or this card, pineapples, or whichever item we want to access. And
then I'm going to increment by the quantity. So plus equals quantity. Now I don't have to
return anything from this function. Because this is really the action that I want to take
by calling this function is to update whatever I have in my cart right now. And to show this,
I'm just going to log this out in the console in the browser, so you can see it when I log out
this cart. And I'm gonna open my console here. So for carrots, I'm going to add three, you
can see nothing happened. That is because I forgot to connect this method to that button.
So let me go up here and add that button. So I'm just going to add it
to carrots right now, here. So when someone clicks on the Add to Cart
button, I'm going to call the add to cart method. Now I need to call it passing in
a few arguments here. So the first one is going to be the type of item that I want to
add to the cart. So this one will be carrots, and I also need to pass in the quantity.
To pass in the quantity I need to use the inventory carats variable. So
I can just pass that in here. I could also just call it from inside of my
function which is Actually what I'm going to do. So let me scroll down to see my function again.
And instead of quantity here, instead of passing in this extra variable, I'm going to just update
this to this dot, this dot inventory, and then get the type from there. So let's see
if this is working. Let me add to cart. And you can see there is definitely a
problem because the input value is a string, and it's trying to add it to the numbers zero,
so then it turns the expression into a string. Now Vue has a very easy way of fixing this. And
this is through a modifier just like we learned about a little bit in the last demo that we
did. So let me go up here to the V model. And we don't want this V model to be considered
as a string, we want to go ahead and cast it as a number. So Vue gives us this modifier
as a shortcut. So v model DOT number. So now if we look in our application,
may add to cart. And I can see down here that my carrots have one item in it, which
is a number so I can add to cart again. And now it's two, and I can add multiples.
And now there's eight carrots in the cart. Let's stop here for this video. And don't forget
to download the related code and try out these features for yourself. In the next video, we
will work on displaying the items in the cart. So now we want to hook up this cart
menu or cart slide out. And right now it's just static content. So we can
only see it from the Products page. And if you look at the code, we go to the
products dot html, I'm going to fold this header, and also the main container, which is
this main part of the page right here. And now I can just see this aside,
which is that cart section on the side. So I basically want to get all of this HTML and
make it available on my other pages like my app page, which is the homepage, so that I can use
Vue j s to trigger opening or closing the menu. And I also want to make these cart items dynamic.
So when I add more items to the cart, it can update the quantity and the price. And I can also
set a variable. So if there are no items in the cart, this will display. Now HTML itself doesn't
have something like an import to import a block of HTML into another HTML file. A lot of people
use PHP or some other back end tool for that. But we can also easily do this in JavaScript. So
we're going to do this in Vue, j. s, actually. So I'm going to remove this sidebar from the page
that it is on right now. And move it into our Vue application. Of course, our Vue application is
nested inside of the app dot html page. But we can move it outside later. So that this menu
will be accessible on all pages in the future. So I'm going to fold this Vue create app. And
now I will paste this HTML aside that I have. Now it's giving me an error or a couple errors
right now because it's inside of a script tag. But I'm going to fix that. So if you recall, in the earlier lessons, we defined the different
components inside of our Vue application. So this is a perfect use case for a component
right now, because it's this reusable block of HTML or template that we want to use on
multiple different pages and also interact with. So I'm going to register this as a component.
And I'm just going to call it sidebar. And now I pass in the object just as before, and
on this options object, I can set the template and then use graves. And now I want to grab
this aside again. And paste it inside of here. And so now I have this whole aside all of the
code inside of my template for this component. And now I can add this To the page with the name
sidebar. So I'm going to go ahead and add it here. And remember that our div wraps the whole Vue
application. So I can put this anywhere inside of that div with ID of app. I'm going to put it
here, actually between the main and the footer, I'm going to put the custom component, sidebar,
and Vue will handle putting the template I have down here where this sidebar element is in the
template. So let me go back to the HTML here, you can see the sidebar is no longer on the
Products page. But if I go to the home page, now I have a sidebar here. So now that the sidebar
is in Vue js, I can start making it interactive. And the first thing I want to do is be able
to hide and show the sidebar. So basically, when this is clicked, I want to hide it. And then
when another button is clicked, I want to show it. So I need to create a variable for this. And
let me go down to my JavaScript down here. So inside of my regular create app here,
in my main options object, I'm going to add an element to data here. And I'm
going to call it show sidebar, false. And now I can come to my sidebar, and simply use
a vi F, and point it to the variable show sidebar. So if show sidebar is true, then my custom
component will show up on the page. If it's false, then I shouldn't see the sidebar at all. And
you can see it's false, I don't see any sidebar. And when I change this to true, I see the sidebar.
Now I just need to add a toggle for this sidebar and change it back to false by default. And now
I can create a method called toggle sidebar. And I'm going to say this dot show sidebar equals
the opposite of whatever it is because it will toggle true or false every time this function is
run. So I'm going to say it equals not this dot show sidebar. So if it's currently false, that
means it will be set equal to true and if it's true, it will be then set equal to false. Now I
just have to call this method. So the first place that I'm going to put it is on this button here,
this cart button should open that cart sidebar. I'm going to find that on the page. Here is that Cart button. And I'm just going
to add an ad click here. Add click equals toggle sidebar, I don't need to pass anything
in so I can just leave it as this. And Vue will automatically look through my methods and find
that method. So let me see if that works. Go back to the page should be able to click on this now.
And yes, it does toggle. Now the next thing I need to be able to do is close it and I need to close
it using this x here. So I'll have to go down to my template here. And here is the button.
That's that x that's in the corner of the header for the sidebar. So I need to add an app click
on this. And I'll have to do app click. And now I want to use the function toggle sidebar. But
because this is wrapped in its own component, I actually don't have access to the
toggle sidebar function from here, I actually have to pass it into this component
to be able to access it. And I can do that here. So I'll pass it in as toggle equals toggle
sidebar, I'm using my method on the vj s object called toggle sidebar passing it into the
sidebar component with the name toggle. So inside my component here, it's going to be called toggle.
So I'm going to have to accept it as a prop and as accepted as toggle. And that will be my function
name. So now I have to rename this function and call it toggle. Let me see if this works. Go to
cart click x and it is not working. So I do have an error here maximum call stack size exceeded.
So let me see what I do. Wrong in the code. So I'm importing the prop toggle, the function
should be called from here of toggle sidebar that is pointing to toggle sidebar here. And, oh,
I forgot to make this point to a Vue variable. Instead, it was just trying to use it as a
string before which was causing an error. So now it should be calling the actual toggle
sidebar function. And let me see that in the code. Okay, it works just as intended now. So
now on the sidebar, I want to be displaying actually dynamic items here. For right now,
I only have one item hooked up carrots. And so I'm only going to be
working with this one item until the next video. So let's hook this
item up. When I add items to the cart here, I should it should update in the cart over here.
Now to do that, I need to take this cart object and pass it in to my sidebar, so my sidebar has
access to it. First, let me do some cleanup here. With this on multiple lines to
make it a little bit cleaner. And I'm going to pass in cart as just
cart. And now I have to receive this prop in my component here. So I'm going to do it here
and call it cart. And now cart that I'm getting in my component is actually that cart object. So
since I'm only working with carrots for right now, I'm going to just assume that and
only add the number here for carrots. So I'll use my double mustache syntax. And I
have that cart variable. So I'll do cart dot carrots, and that will be the number of
carrots that I have. So let me go back to here and automatically updated. Let me add
three. And my cart now is quantity three. So if I add, let's add five more now this quantity
eight in my cart. So now my cart is dynamic. Of course the total should also be updated based off
of the quantity should be price times quantity equals the total for that item. So let me do that
really quickly. This is the total number. So I'm just going to have to do this. And let's say cart
dot carats times the price which it says it's $1. But here it says 482. So I'm going to use this
price because $1 isn't that interesting. So I'll do times 482. And then before that, I need to
put in dollars. And let's see if that works. To add to cart. Now there is an error, let's see
what the error is unexpected token with a dot. The reason why it's complaining is because $1 sign
followed by curly braces. in JavaScript, whenever you put that syntax inside of the backticks that
we have around this template here. It's called a template string. And it will parse whatever is
inside those outer curly braces as JavaScript. So thinks we're trying to pass in a JavaScript
object. And it's complaining because cart carrots is not a valid key. So the only thing we have
to do here is actually escape the dollar sign. So JavaScript doesn't think where you're trying
to use a template string and pass in a variable. And then Vue can just parse the double curly
brace syntax on its own. This should work. So let me go to cart now my cart opens as normal.
You can see there's zero carrots. And now if I add two carrots to the cart, and now gives me the
correct total of 964. Now I also want to have a total of all the items in the cart. I only
have one item now but I will have more items soon. So I'm going to go ahead and add a function
for that. And then we will hook up the rest of the items in the next video. So back in the code
here, this is the total that I want to update. So I'm going to add this and escape that dollar
sign that comes with For the double curly braces, now I could create a formula just in line here and
say carrot cart carrots, times the carrot price, plus the second item times that price, and so on and so on. But that's not going
to make a lot of sense. And that doesn't scale for multiple items. So what I'm going
to do here is actually add a computed object. And if you remember computed
watches the changes in variables, and we'll update the result. So I'll
call this computed function cart total. And on my cart appear. Right now I have just
the number of each item. So for right now, I'm just going to hard code the price down here.
So I'm going to return cart dot carats times the price, which is 482. And now I can
take this computed variable that I created, and put it in here. And now the cart total,
that amount should be updated every single time. Let's see if this works. Add to cart, open my
cart. And there is a bug because it's not opening and stepping through trying to figure
out why the cart total isn't working. And it is because I have accessed
it incorrectly. So cart dot carrots has to be accessed This is inside of JavaScript,
so I need to access it on the this context in my component. So I have to access it on this card
carrots, and that should come up with my number times that number. So let me go back to my
page. And now it opens. And if I add items, I can see it's $24.10. Of course this isn't
that pretty. Sometimes it rounds it to one, or sometimes there's only one decimal, and
sometimes there's like 10 here. So let's just run this really quick using something built
in in JavaScript. So we just get two decimals. I'm going to wrap this here, that two fixed.
And then the number two. And let's go back to the browser, I'm going to open up the cart, add a
few items. And now it's at two decimals Exactly. Always two. Okay, I'm going to leave it
there in this video. Again, please try out implementing these features on
your own from the example code, you should be able to check out the starter
branch called homepage, one from the repository and start exactly where I did at the
beginning of this video. In the next video, we will cover adding all of the rest of the items
to the cart by importing them into our JavaScript. So we can use loops to make our code more
efficient and not have to hard code everything. In this video, we are going to pull in dynamic
content to populate our page. And that will be from this food dot JSON file. So this actually
has a list of objects of all different kinds of groceries that we are going to display in our
app. It has some information, like the names as well as the price. And then even if we
want to add a filter to sort by the type. So how can we pull this into our application.
Actually, we are going to use lifecycle hooks in Vue j s for this. If we come to our
main Vue application here, below methods, I am going to add mounted hook just like we had
before. And inside of here, I am going to fetch this JSON data. And that's going to be an
asynchronous call. So I first need to fetch this from the file name, which is food dot JSON. And
I'm going to call this the response. And then I need to call the JSON method on that response.
Which I put on this line, and that will be data. And actually I need to add a weight to these
calls. So res dot JSON, I can call that method. I'm going to await this as well. And then
because I'm using a weight, I need to add async To this mounted method. So now I've
created the mounted lifecycle hook, I get my data, which is the array of all of
the food objects. And now that I have my data, I am going to set it on state here. So instead of
inventory here, I'm going to replace inventory, just get rid of all this dummy data that I have
right now. Set it as an empty array. This will definitely break my application right now. But
it's okay because it's a step toward fixing it. So now I'm going to set this stat inventory
equal to data. Let's see if that even works. And I'm going to come to my Vue here, I can
see my root. And I can see that the inventory in my root element here that I have all 15
items. Good. So I know my data is working. Now, the next two things I need to do are display
that data on this page here. And so these are just three recommended items, actually, all
of the products will display on this page. So for the homepage, I'm just going to display the
first three and slice that list as I loop over it. So now that I have inventory, I'm actually
going to come up here to my main container. And I'm going to come to the recommended
section and fold all of these cards and get rid of the last two,
because I'm only going to need one for my loop. And now with this initial
card, I'm going to turn it into a V for loop and loop over each item in that
inventory array. So equals product in inventory. Let me just see what this looks like
really quick. And yes, it tries to loop through every single item in the whole inventory. So I'm
going to slice it at three items now. And I can do this because inside of my Vue directive, I can put
valid JavaScript. So we're going to do dot slice from 023. And now we'll go back to my page.
And you can see I only have three items. Now, of course, it is only displaying carrot,
because that's all still hard coded. So let me put some dynamic content in here.
And first with the name, I'm going to put product dot name. And then I believe it's product
dot type. Yes. So here, I'll put product dot type. And for the price, now I do have prices in two
different currencies, I'm just going to use US dollars for right now. So I need to
access price dot USD. And so here, I'm going to go ahead and escape this. And then
do product dot price, dot u, s, d. And actually, this is just an HTML template. This isn't inside
of a JavaScript template string, so I don't need to escape that at all. And that should be all of
the dynamic content that we need for right now. Let's actually go ahead and update the icon
as well. So that would be product dot icon. Make sure that's the right. One. Yes,
that icon. Okay, so let me go to the page. Okay, so the icons not working, but all the
other data is displaying quite nicely. So now we want to add functionality so that the quantity
properly updates and we can add it to the cart. Of course right now, all of these elements have
the same v model. So that's why they are marrying each other. So let's change that. Now I'm going to
go to the V model here which is inventory carrots, but I need the inventory of the correct item
instead of just hard coding carrots here. So because these numbers are In order or because this
is an ordered list, I'm going to come to my loop and get the index. Of course, I could use the ID
as well. But I'll just use the index in the loop here. And actually, I almost forgot, I also need
to add a key here since I am looping. So let me add that key. And I'm going to come down here,
and inventory, I'm going to pass in that index. And then I'm going to add a new attribute called
quantity. And so this should model to an attribute called quantity, which is not currently on the
objects, but that's okay, I'll just leave it off. And this should just add the quantity key to the
object as needed. So let's see if this works. Let me go back over here. I'm going to add
one here, you can see they're not all mirrored for each other anymore, I'm going to add it to
cart. And let me see how this represents in my Vue data here, I can come to inventory. And I can
see quantity of one. Whatever number I've put this number mirrors it. But now I need a way to add
this to the cart. So let me set up the cart then. And here at this add to cart function, I do
need to change it because I need to pass in instead of a string, the dynamic name of
the item. So I can do product dot name. And actually here, I didn't think of this, but
instead of inventory and getting the inventory at index, I, I already really have that in this
loop. That's what the product variable is. So I'm just going to replace that.
And that should work just fine. Now, of course, I don't really need this
index anymore, because for the key, I can use the ID of the product. So let me just use
that product ID and that should work okay. And then this should also mirror
object to let me see if that does. Yes, and the quantity is married. Okay, now for the cart, passing in the product
name as Add To Cart. Let's take a look at the add to cart function. We are passing in the type
here. And then saying this duck card duck type. So it will be like this cart dot radishes plus
equals whatever the amount is that this that inventory. So we do need to do one
more thing here, we could either search and find the item by name in the inventory, or
the easier thing to do would be to pass in the index of that item. So that's what we're going
to do. And while I'm changing this, instead of type now, I think it makes more sense to call
it name because it is the name of the item. And we're using type for the type of item
like vegetable or fruit not the name anymore. So now to access it in inventory, I want to do
index and then dot quantity. And that should work. But we have to actually passing the index here.
And up here, we're actually going to be passing in the index actually. So we're going to
take the index here. And now add to cart. Okay, so we are getting not a number for
these values. So I actually want to see what we are passing in or what gets
passed in to the function. And so to debug the function quickly, I'm just
going to console dot log and name and index. Now back in the code. So the arguments are
getting passed into the function just fine. So stepping back through this, I can see that
my problem here is that I am doing a plus equals on cart or this cart name when there
is no value for that name in the cart yet. And by the way, I'm going to go ahead and
get rid of my dummy data. In the cart, and here, I'm just going to put a simple
check. So if not this dot cart name, then I'm going to set this
cart name and equal to zero. And now this statement should work. Okay, let
me try again. So here, I'm going to do two. And this should update. Let's see. Okay, yes.
So it's taking a minute, for some reason, buy, it shows the correct number of each in the
cart, no more, not a number. Now that shows it on the cart over here, I want to show it
in the sidebar. Right now in the sidebar is hooked up to only look for carrots.
So let's make the sidebar dynamic now. So if you remember, the sidebar here is
in this template. So it's part of the custom sidebar component that we made. And we are
already passing the cart in here. Now we actually need more information because the cart is only
showing us the number of items in the cart. But we also want more information from those items,
such as the price. So I'm going to come up here to my sidebar, and after cart, I'm going
to be passing in the inventory as well as inventory. And now I can receive
that as a prop in my component. So basically, we have to loop through
all of the items in the cart and display their information now. And we have a table here.
So we have all of the headers for the table. And then we can loop through these rows
and basically make as many rows as we want. So I'm going to go ahead and add a
v4 here to loop through each item in the cart. And here, I do need to use the
index, I will be using that as a key here. Okay, and now these are being looped through in
sidebar. So if I come to the sidebar, I should see no items right now, of course the totally
needs to be fixed. And now I can see I have this item. And now I have another item. So
now I need to get rid of these hard coded names. Now to do that, I'm going to go ahead and grab
the key for these items in the cart. And actually, because cart is an object, this index is
actually going to be a key. And then the third one is index, or just I. So now I have
access to the item name, which is the key, the item quantity, which will change this to
the name, quantity. And here, I can change this to that key and we should see the names of all
of the items in our cart. Let's test this out. Let me add different items to the cart,
should see radishes and artichokes. And in the cart, we do indeed see radishes and
artichokes. Now let's display the quantity. So here, we can get rid of this and say
just quantity, which we're pulling off of the object in the cart. Of course, we already
know that should work when we add an item here. And quantity works. Now price is a little bit
trickier. Because we don't have the price stored on the cart, we actually have to search through
inventory for the price. So we're going to make a helper method for that. First, let me escape this.
And then we're going to call get price Asin the name of the item which is the key and we will find
the price and return it based off of the name. So after computed here, I'm going to add
methods for this regular methods object and add that get price. And basically
we can access this dot inventory and to do a dot find. So we want to
find one of the inventory items. So I'll call each item product in the function that
I pass in, and find will loop through all products in the inventory and try to find whatever item I
want. So I want the item where the product name is equal to the name that I'm
passing into the function. And when I find that product, I'm going to set
it equal to a variable here. kind of confusing, if I call it product again, so maybe
I'll just call this one p instead. There we go. And now for the return function, now
that I have the product saved in this variable, I can do product. And it should be dot
price dot USD again. So dot price that USD. And that should return the price of the item. And
let's see if that works. So let me get one here and Vue the cart. And I can indeed see the
price. Let me try that for artichokes too. And I can see the price and quantities of the
item correctly. Now, let me update the function for total. And so total here needs to be dynamic,
based off of the whole cart really. So to do this, I'm actually going to use a helper method. So
what I'm going to do is take this out of computed, and instead use it as a method. So since it's
not computed as a method, I'm going to call it a verb. So calculate total. And I'm going to
go ahead and rename the method call down here, of course, I'll actually be calling that as
a function now. And I won't be needing this line of code anymore. So now we basically
need to calculate the total based off of the quantity in the cart. And then we have to
look up the price in the inventory. Fortunately, we already have a method to be able to look
up the price. So we're going to just use that. And the easiest way to do this is
actually to do object dot values. And so object dot values can give me an easy
array of values out of an object. And because cart is an object, I'm not going to loop through it
directly, I'm just going to grab all of the values out. So I will pass in cart. And now I have an
array of all of the values here, which are the quantities that I want. So out of that array, I'm
going to reduce it. Now the reduced function is just a built in JavaScript function, where I save
an accumulator. Some people like to call it a Some call it an accumulator, because that's what it
uses on MDN. And basically, I'm calculating a sum on each iteration through the loop. I also
have my current item that's being looped through. And then I can also get the index of that item
in the function. And basically, what I want to do is return the accumulator, sum total, whatever
you want to call it, plus the current item or the current value, because I'm looping through all of
the values on the cart here. And I need the value times the price. So I'm going to have to call
this dot get price. And then I need to pass in the name of the item that I want to get the price for.
So the easiest way to do that is to also make an array of names. So I'm going to do that by using
this time object keys. And I will do this cart, get all of the keys this time off of cart.
And actually, I forgot to put this here. And so I will do the current
value times this dot get price. And now that I have the names here,
I'm just going to look up by the index. So I can pass a names index to that this dot
get price function, and that should work. For the function. I forgot to put an arrow
here. And now for the total variable. I just stored it in a variable to explicitly
name it. All I need to do now is return the total now, this time function works, there
might be a more optimized way to do this. This is just to demonstrate how to calculate a
total using a VJs method for this application. And it's basically just using regular JavaScript. So
let me add items to the cart here. And of course, of course, this total, we haven't done yet. But
we do have two radishes, and the total says $2. So let's add some artichokes. And now we have a total
of $30.32. As you can see, those are the correct values, what I believe is happening is because
objects are unordered, and arrays are ordered, that the names and the object values, they aren't
being listed in the array in the same order. So I'm going to have to instead of making two
separate arrays here, I'm going to get rid of this one. And here, I will just have to change
this to entries. And now my current value here will basically be in array, that will be the
key and the value, each time looping through this larger array. So for the value, now, I
will have to access it at the first index. And instead of names here, I can access the name
at the current item at the zeroeth index, that all looks good. The last thing I'm
going to do is add an initial value here. And this means that the accumulator will
start at zero. And also, if there are no items in this array, which there aren't any to start,
that means the number will just be zero total. And for here for the total, actually,
I'm going to use that method again, that we use before, which was too
fixed. So I could do it to two decimals, which is what I want in my cart. Let me see if
this works. And this is exactly what I want here. So let me add items. Yes. And the
price is exactly right. One artichoke, and the price still works there. Now what about
the total here, that should be easy enough to do with our get price method. So let's go down to the
total. Right now it's hard coded as carrots, which doesn't exist. So now I can do just the quantity,
which is the quantity of the item in the cart. And then I'll call the get price method.
And I'm going to pass in the key, which is the name of the item. And so that should
multiply by the total. Let's see if that works. add an item and check out the cart.
And we do indeed see the total here. Now it still says no items in cart, let's go ahead
and fix that. So this should only show if in fact, there are no items. And so I'm going to add a V if
here. And just to speed this up, we're going to do object that keys and then check the cart object.
So if there are no keys on the cart object that will be zero, which is a falsie value.
And let's see if that works. Let's go down here to radishes, add one in the cart, we
are still seeing this no items in cart. So I believe I have to do length
here. Let's see if that works. Okay, that does work, but I have it
backwards. So I basically need to do if not, because if the length is zero, I
want to show this. And if it's not zero, then I don't want to show this no items in cart
because there will be items in the cart. So let's see if that works. Let's first go here, it does
show no items in cart. And now let me go here. And now it changes to the item in the cart.
And all of the totals are shown correctly and the quantities updated and all of that
stuff. The only other thing I want to do is provide full CRUD operations, and this delete does
not work. So I'm going to hook up the Delete now. So you can see the Delete is here on this
button for remove. And so I'm going to add a function here and actually this function
will have to be not inside of this component. But inside of the parent component, which
is my main Vue application in this case, so I'm going to do a click. So when this
button is clicked, I'm going to say remove item to remove the item from the cart, and
then I need to pass in the name of the item, which is the key. Now this remove item is going
to have to be a function passed in as a prop here. Because I can't mutate props, I couldn't change
the inventory, or the cart actually directly from this component, I have to change it from
the parent component where it originates. So I'll take a remove item function, let me go ahead
and pass that in. Remove item equals remove item. And now I have to create that function here as one
of these methods. So let me add that remove item, this will take in the item name. And I am
going to remove it from the cart basically. So I can just remove JavaScript, delete
this cart name. Let's see if that works. Let me add some vegetables to my
cart. And now I will remove them. And it does not remove let's see if I'm getting
an error. Remove item is not a function. So let's see why it's not considered a function. I
do have it in methods here, remove item. Let's go here. This is remove item
that I'm passing into my sidebar. I'm also accepting it as a prop in
the sidebar here. Let me get rid of computed. So it's not recognizing this as a
function. So what I'm going to do is rename it in the child component. Now, this is a
workaround only for the CDN, you won't have this problem if you were using Vue JS from NPM. But I'm
just renaming the function in app component here. There we go. And of course, I need to pass
it in as the name remove. So I basically gave it a different name for the child
component and for the parent component. And let's see if it recognizes this
as a function. Now, I will come here. And I can remove it from the cart. Awesome.
Of course, when I add things to the cart, I do want the number to clear here. So let me take
care of that really quickly. In Add To Cart here, just really quickly, I'm going to set
this to zero. Let's see if that works. And back to zero, and it is in the
cart now. Awesome. The only other thing is that the cart does show zero items, even
when there are items in it. That's because the number is not dynamic. So let me change that
really quickly. Here, inside of the parentheses, I'm going to change this to be dynamic. And
I'm just going to call the variable total quantity. Okay, and now I
need to make this variable. So what I'm going to do is
create a computed object here. And I'm going to say total quantity is basically
the sum of all of the quantities in the cart. And to do this, I'm going to use another reduce
method, I'm going to say object, that values pass in this cart. And then I will reduce
those to sum up all of the numbers. So I have my accumulator and my current
value. And then all I need to do is add the accumulator and current value together. Of
course, I'll set a default of zero here as a starting point or initial value. And I'm just
going to return this directly this time. Let me see if that worked. Right now it says zero, but
let me add items Notes three, let me add one more. And now it's four. So the quantity is working.
If I remove one, now it's just one. So that is a dynamic value now. And that is basically
it for the homepage here. In the next video, we are going to move the Vue JS code outside
of the app dot html file. So we can see how it can work in multiple different pages. And
also some of the struggles that we might run into trying to build a multi page site via the
Vue CDN and trying to do things like share data across pages and stuff like that. If you
want to see the starter code for this video, make sure you check out the branch and the repo
called homepage, number two, or homepage, two. Hi, everyone, welcome back. First, I want
to reVue what we did in the last video, we connected the cart slide out draw menu on
the right here and made that fully functional. And then we added an actual loop, as well as
functionality to be able to add items to our cart here. Now this is only one page, of course.
So we also have the Products page here. So if I go to Products page, you can see the URL
changes to go to the products dot html page. Now if I look at this in my code, so let me open
up the source. And this app dot html file. Again, you can see here is the header with all of the
links on it. I'm going to fold that real quick. And then you can see the different sections of
the page, including that sidebar that slides out that we actually want on every page. But now it's
kind of just hard coded into this homepage. I can also go to Vues here. So you can see in the header
actually. So when I click on products, it goes to Vues slash products, that HTML. So it's actually
navigating me to this products dot html page. And if you look at the header
here, here's the whole page, including a completely separate div with ID of app
where we would have to inject our Vue JS code. You can see we already did that on this page, because
our Vue j s is in the script down here. And we are rendering it or mounting it inside of that
div. But if I go to products, we have no JavaScript, no interaction,
everything is hard coded. We also have a duplicate header. So this
is exactly the same thing as the header on this page is just copy pasted into the HTML on
this page. Of course, we don't want to do that everywhere. We don't want to have a copy
pasted header for all of our different pages. Not only that, we would have to copy
paste the whole cart sidebar as well. So to make this code reusable here, we need
to extract these things into other files. Now, this is not easy to do for plain HTML. But
we can use a Vue component like we did before with the sidebar. So I'm actually going to extract
all of this out into a separate JavaScript file. And now import this file into my HTML. And you can see my page is still working. My cart is still fully functional. And what
this allows me to do is now take this file this JavaScript file that I have separated and
import it also into my products dot html file. And I'm actually going to grab both of
the script tags so I can also have my Vue and I'm going to put them at the bottom here,
except I'm going to have to go up a directory here because my app.js file lives outside of my Vues,
right? Here's products. And I need to get upload folder to app. So I have to do dot dot. And
that should reference the correct app.js file. Let me see if that's working for go
to products. And you can see the cart page doesn't open. But that's because I
have not hooked up the cart button yet. So I will have to copy this over from the app dot
html file for right now. So if I go here, I can just take the same code. And now it should
reference that same toggle sidebar function, and also display the total quantity correctly as
well, because I am importing the same Vue j s code in the script tag here. Now, you can see that the
cart variable displays just fine on the Products page. But if I click here, of course, the cart
doesn't open. Because the cart is only available on this page, I only have the sidebar
component here. And the sidebar component, you know is actually a custom
component that we made in vj s. So we can put that on any page where we import
the vj s. So I'm just going to put it here below this main tag. And with all the same variables,
there should be fine, because we're sharing the same Vue JS script. Let me save that. Now
you can see I can toggle the cart here. And all of this is pretty much the same thing that
we did on the homepage, down here where we looped through the different types of foods, we would
do the same thing over here on the Products page, loop through them hook up in each individual
number, then hook up the Add to Cart button so that it would actually display in the cart over
here. Now if I add items here, may add a couple to cart can see I have three in my cart here. If I go
to products, you can see the page refreshed. And now there are no items in my cart. So though there
is some functionality to this application. So far, there are a few problems that we have run into
with just using a CDN to import Vue j s. And that is how do we share data across pages and
across pager refreshes. So here at the homepage, when I add something to the cart here, it
leaves the car as soon as the page refreshes. So as soon as I navigate to another page,
it's gone. Now how would I fix that problem. So generally, in front end applications,
we would want to do something like persist our data or save our data somewhere. One easy way
to do that in the browser. And one very common way is to go here in application. And you can
see there's different types of storage. This is in browser storage. And local storage
will persist even if the page is refreshed. So we can actually save the data like our current data
into local storage here. And then if we refresh or anything, we will just automatically try to
pull anything that's saved from local storage for the way our application is set up right now.
That would be every time we navigate to a new page, we would have to check local storage, see
if there's anything in there and then pull it into our application. It's kind of a workaround for
our setup. So one way to fix this would actually be to create a single page application with Vue
where the front end would actually do the routing. Instead of our server. In this case, we're just
using a live server in VS code. But our servers serving at pages every time we go to a new URL
here. And that's why it has to refresh because it's coming from the server. Whereas if we make
a single page application, there will be no page refreshes, we will go seamlessly from page to
page because our front end in other words, Vue j S will be routing us to different pages. The
second problem, as you can see is sharing code. We do have some duplicate code across pages.
Of course, we are reusing the same sidebar template here, this sidebar template. We just
registered it as a Vue template, a Vue component called sidebar and we can use that on any page.
Now. We could do the same thing with header as well. And we would probably do that if we were
going to build an application using the CDN. We get to extract this into a template as well.
And then we would have to do the same thing for the past orders page. Of course, none of this is
dynamic or set up yet. But the easiest thing to do is actually to set up our project with something
called the Vue see ally. As our code base grows, it will be very difficult to manage many different
components, if we are managing them just importing different files into all of our different
HTML files. But there is a much easier way. And that is with the Vue COI This is why it was
created. The vcli basically gives us one command, Vue create, and our project name, and
then it creates a whole project for us. It walks us through a setup wizard asks us
what features we want. And then we'll create all of the files, folders and build tools
necessary for a robust front end single page application. So in the next video, we are going
to take all of our code currently in HTML files and our JavaScript file and convert it to a Vue
COI application. I'll see you in the next video. Let's get started with the Vue COI,
I am at sea ally dot Vue j s.org. And I'm just going to click getting started. And
if I go over to the side, click on installation, I can see that it is prompting me to globally
install this Vue COI package at Vue slash c li so that from my command line or terminal, I will
be able to use a Vue command to create projects. Now you might see some places on the internet
that install a different package without the at sign in slash dist Vue dash c li or something
like that. That is an older version of the package Vue basically has its own namespace and then each
one of its packages are after the forward slash. So to install vcli you can copy this command
here. I'm going to go to my terminal. Now I have the Vue COI installed, I can
check and make sure that it's installed by checking the version. Right
now I have version 4.5 point 11. And now I want to use it to create an actual
Vue project. And I can do this through the Vue, create command, and then give it the name of the
project that I'm going to create. If you want to see the documentation for this command, you can
come over here under basics to creating a project and read about how Vue create works here.
I'm going to go ahead and say Vue create product and cart as the name
of my project and click Enter. Now, if you've used some tools like create
react app, you will notice that here, it's a little bit different. It doesn't just
bootstrap the whole project for you right away, you actually get to pick your own options, and
the packages that you want to install and use. These top four options here are actually custom
options that I have created myself. Vue gives us these two defaults right now one is for version
two of you, and one is for version three. And then it also gives us the option
at the bottom to manually select features. So I'm going to go ahead and do that
just to show you how it works. So I basically use the arrow keys to go down and then I can
click enter when I want to select something. Now you'll notice that this list here is multi
select. And if I press spacebar, I can select or deselect an item. Of course I want to choose my
Vue version because I want to use version three. I definitely need to have Babel setup for me for
transpiling my Vue code, I'm going to need routing in this application. I'm also going to use state
management with Vue x. But I'm going to add that later to show you how to add a Vue COI package
after you've already set up your application, CSS preprocessors or things like sass, if you
think you will want To use sass in the future, it's a good idea to go ahead and set it up. Now,
I believe this also works with less and stylus as well. And then I definitely want linting and
formatting in this project. And I can optionally select testing if I want, which, but I'm not
going to do that this time. So once I'm ready, I'm going to hit enter, it takes me to the next
step, I can choose the version of uJs, arrow down. And I'm going to choose version three, use history
mode for the router. This is a pretty small coding change. But it's usually what you want to in
a project. This basically only affects the URL of your project from a user point of Vue. So
if you want your routes to be after a hashtag, it will use hash router. If you want your ads to
be after just a normal forward slash, like any website, you would navigate to in your browser,
then you can just go ahead and use history router. And I'm going to use history router. Now it's
asking me to pick a linter, and formatter, so I'm going to go ahead and pick es lint
plus the standard config that it has for VJs. Click enter lint files when they're saved, I'm
going to choose to put my configuration in the package dot JSON this time, just so I don't have a
bunch of extra config files. Usually when you have larger projects, you want dedicated config files.
So it's not cluttering up your package dot JSON. Do I want to save this as a preset? No, I do not
this time. But if you remember at the beginning of this walkthrough, the four top options, those were
presets that I had saved in the past, but here I'm just going to say no. Here, it's basically setting
up my whole project with the file structure and everything. And it's also running an npm install,
you can see it successfully created my project. If I list the folders inside now, I have
this new folder that was created for me by Vue JS called product and cart. I'm going
to go into that folder. And you can see when you spawn up the project for me, it
also initialize a git repository for me, and saved all of the changes that it did initially
as a commit. So let me open this up in VS code. And I have my complete project created for me by
Vue. In the next video, we will look through all of these folders and files and give you a little
bit of a tour of how your Vue project is laid out. Let's look at all of these files
and folders Have you spun up for us. Now looking at this, this looks pretty much like
the last project that we worked on with static HTML, CSS and JavaScript files. And that was by
design, to give you the same style of coding and file structure that you would be using in a real
Vue application. This however, is much much nicer. Starting with the Vue, see ally gives us
a lot more features out of the box that we can see in the package dot JSON, we have three
scripts here by default, there would be more if you choose to install the testing packages as
well, because we installed a linter, the vcli gives us this link command. And then it also gives
us our main two commands for the Vue application for development locally, it gives us this serve
command, which basically calls this package vcli service. That's from Vue, j s gives it the serve
command and it will run a development server for us. So there's no more of the old complicated
server setup that we had in the last version of this in the last application. The build command is
really for when we want to host our project live. This will generate production ready files for
you like your HTML, CSS, and JavaScript. So you can deploy them and have a live website somewhere.
We're just going to be talking about this command in this video. And to give you an idea of
what it does, let's go ahead and run it. I can use NPM to run the
command. So NPM run serve. And now my app is running at Port 8080.
If I highlight something on the terminal, it automatically copies when it
come to my browser, open a new tab and I can see it gives me an app or already
set up out of the box. And because we chose to install a router as well, it installed the default
Vue router, which is also called Vue router. And you can see I can go to different page routes.
Now this isn't the same as our last application, because there's no page refresh in between page
routes. These are not HTML links. This is just a JavaScript router, rendering hiding or showing
different pages of this application. You also notice from the homepage, it's just Port 8080.
When you go to the about page at ad slash about, if we look in the public folder here, you can see
here's our HTML page. And we have a div of ID app. And this is where our app will be injected.
But also when our application is built. Under the hood, this Vue COI service command is running
Webpack, and bundling all of our files together, and also handling running Babel to transpile our
files, and so all of the JavaScript and everything will be injected as script tags as well here.
But we generally don't have to worry about this index dot HTML file in a Vue project. Because
again, most of what we will be doing is in the source folder right here. So we have a main
dot j. s file that is always created for us. So this is basically the same thing that we did in
the previous application. If you do c Vue to code, this file will look a little bit different. But
you'll still be able to see the different parts, just the organization and syntax is a little
bit different. Just like before, we have to pass in a root component, we chain on any packages
that we want to use, in this case, the router, and then we mount that to the DOM.
So inside of the div with ID of app. And you could also rewrite this as const app. And then app dot use router, and then app dot
mount. That's a bit easier to parse through as you add more packages. Now, when we are looking
at this initial page, where does all of this come from? Let's take a look. So we have our
main component app. But you'll notice in app, there's no real content here. All it is, is
a div. This is basically the top navigation. Now, where did this router link come
from? This is a custom component actually. And if you look at our main j s, when we use
App dot use router, we are actually given some components like router link, as
well as router Vue. Now router link is actually a substitution for using
the anchor tag to link to another page. Except router link is made by Vue router,
specifically for single page application routing, where our JavaScript handles the routing.
Instead of linking to a separate HTML page. Of course, we only have one HTML page. And all
of our static content is injected into that one page. And the router handles intercepting the
route and making it appear as though you've navigated to another page. While really it's just
showing and hiding different elements on the DOM. So we have these two router links. And then
what does router Vue do? So router Vue, is actually our page content. And our router
will handle replacing this router Vue tag with whatever component we tell it to in our
routes file that we are about to look at. So router Vue is just a temporary placeholder
for whatever we put on the page. And you'll see as we navigate to different pages, those home
and about links at the top of this file. Those will stay no matter what page we navigate to. But
all of the content below it will change because those are the components getting injected into
this router Vue area here. If we look into our router index.js file here, we can see that we
are using the Vue router API to create a router and when we create a router here, we are
passing in two things. So the routes, which is an array of all our routes that we
have in the application, and then history mode, it set this up for us because we chose to
use history mode. And Vue is handling all of that under the hood. But let's talk about the
routes here. So we have the default home route, which is this page. And then we also have the
about page, which is found at this route. Now, you don't have to worry about code splitting,
and lazy loading and all of that other stuff. Those are more advanced routing concepts.
So I'm going to get rid of that line. And then just import the about component. Just like the home component. Now you basically
define routes here. And instead of importing the components that you want to show on a page
into your app dot Vue, you just use a router Vue tag here. And then you import any of your Vue
components, like home and about into this file, you define the path where that component
can be found it the name of that component, now the name is mostly used for routing, and then
you tell it which component will be found at that path. So at the home path, we're going to find the
home component. Now, where's the home component, you can see that it is in Vues slash home. So
let's go in here. And we can see that this is the component, it has an image, which is the Vue logo
on top. And then it also imports another component into itself. Now this component is not in the
Vues folder, it's in the components directory. Now why is it in the components directory, instead
of just one folder for all Vue files, basically, in front end applications, files are usually
split up between Vues, or pages. So basically, anything in this Vues folder will be connected to
the router. So they will have their own routes, there'll be their own pages. Anything in the
components folder are things that are imported into other components. They're meant to be parts
of pages or reusable components that you use throughout your application. Basically, anything
in the Vues folder is connected to the router. And if it's not connected to the router,
and just imported into another component, then put it in the components folder.
And you'll see at the home route, there's a Vue image at the top. And
then there are all of these links here. And that's exactly what we see in the home route. Now if we go to the about page, it's not importing
any other components or doing anything fancy. There's only this h1. So I header with that text,
which is what we see when we go to the about page. assets, of course, are a place for usually
CSS images, anything like that to live. Sometimes you will see other folders created here
in Vue projects. But these are the basic ones. The only one that we are going
to add later is the store folder. And we'll talk about that in a few videos.
In the next video, we are going to start transferring our content over from our old
static application into our Vue application. Let's start moving things over one
by one starting with the homepage. I'm going to go over to my original code here
into source and then go into my app dot html here. The first thing that I need
to grab is this header. Now I do have some JavaScript functionality in
here and I'll handle hooking that up in a minute. But let me just copy paste for right now.
And move this over to a new file. Now I'm going to need it on this homepage here. But since
this header is actually my app wide navigation, I am actually going to want to replace the
navigation here. So that I can use this and see this on any page. For right now I'm going to get
rid of these. Now there's a bit of cleanup that I need to do here. Because these anchor tags need
to be changed to the Vue router router link tags. And now I need an actual route. So
instead of pointing to an HTML file, I am going to give it a route that will be
in my router here linked to a component. So I have this products dot html here, what I'm
going to do is changed that to slash products. Of course, this can't be an H ref, this will be
two, since that's expected by the router link, also need to change this from h ref to two. And
I can just call this route past orders get rid of the dot html. And here as well change this to
two. And this should just be a forward slash. I'm not going to worry about this yet.
This last router link at the bottom, I'm going to just comment that for right now. And
basically I need to create these three components that are linked to the routes. Now I already
have the home route here that is linked to the home component, I'm actually going to get rid of
about and I'm going to change this to products. I'm going to have to create a new component. Now let me delete about from here. And let me create a new file.
I'll call this products dot Vue. Now this is a little bit different. Instead of
calling this just a regular JavaScript file, with the extension j s Vue has a custom file
extension, which is dot Vue. All of these dot Vue files are parsed by the Vue and web pack setup,
that the Vue COI sets up for us. So using these dot Vue files, we can put our HTML template, our
JavaScript, and even our CSS all in the same file that gets parsed and all put together and
bundled by the tools that vcli sets up for us. Now I have a new file, I'm just
going to create a template in here. And I have four spaces, I'm going
to switch to using two spaces for tab spacing. And I'm just gonna
put h1 products for right now. Alright, before we get too
far, let's see how this looks. And we do have a Products page and home page
now. But of course, this is completely unstyled. Let's pause here and start to bring over
some of the styles in the next video. Let's start to move our styles over. Now our styles are going to live inside of this
assets folder. And I can go ahead and create a folder inside of there called styles.
Now how do I use styles in my project. If you come to this app component here, you will
notice that there is a style tag at the bottom of the component. And these are what is providing
custom styles for the application. If I look in my browser, this is what is styling and centering
the elements. If I get rid of these styles, this is what it looks like without
any of those custom styles. In any Vue component, you can add styles
directly inside of that component. So if I wanted to do something I could
change all h1 tags to the color of Blue. And you'll notice this is just plain CSS
here that you can write inside of these Vue files. Now, if I go here, you can see that this is
an h1 tag, and it has changed to being blue. Also on the products tag that is blue
as well, because that is another h1. Now, if I look at this, though, those h1 elements
are nowhere to be found in this component. Those are actually in other components. But by default,
the style tag globally affects anything in the application. So if I put a style tag here, even
though it's in the app dot Vue file, anywhere in my application that has an h1 tag can be affected
by this. Now, this is generally not good practice. Because if you want to globally change a style,
you should put that in a separate style sheet. So in some other dot CSS file, here, if I'm
putting styles inside of my app dot Vue file, generally, what I intend to do is only let it
affect the app dot Vue file. So it won't change styles in any other component. Right, it will only
affect whatever is in my template in this file. And that's why I use the scope keyword here.
Now, now that I've added the scope keyword, so you can see that the text changed back to black.
Because now that I've scoped this, it is only affecting styles within this Vue component, not
in other components throughout the application. Now, if I wanted to add an external stylesheet,
let me just go ahead and create a temporary one here. I'll call this main dot CSS. And let me
paste in my last style. And I'll change the color. This will not affect my application yet, because
I have to import the CSS file. Now instead of importing this into one of my HTML files, what
Vue does is allow me to import it directly into my JavaScript. So generally, that would be this
main.js file, what I can do is import from assets, styles. And then that main dot CSS, and the Vue,
see ally set up Webpack for me in such a way that I can import styles directly into my JavaScript.
And it is all handled by the tooling. So now if I go back to my browser, it's
a little bit darker. But you can tell that this is purple now. Because I am
importing it globally, into my project from this main dot CSS file. Those are the basics
of how you import styles into an application. Now, if I come back to my original static application
with our HTML files that we were using, if I come to styles here, you can see that these
aren't just CSS files. They are sass files, for the most part. So how do I get these into
my project if they aren't standard CSS files. So Vue also has built in ways
of handling this, let me copy these styles. And I'm going to delete this
styles folder here. And I'm going to paste. So I pasted in this styles folder from my other
project. And now if I look in this folder, there is one file called style dot SCSS, which is
a sass file. And this imports all of the rest of the files here, all of my other sass files. Now
it is this file that I really want to import into my project to get all of my styles. I'm going to
comment this out. And now I'll import that sass file directly from assets slash styles, slash
style dot s CSS. I'll save that. And now you can see that it is giving me an error saying can't
resolve sass loader so it's trying to load those sass files. But since they aren't regular CSS, we
have to add another module to be able to import those files. And that is like it says SAS loader.
If we look in the Vue COI documentation, and go to working with CSS under development, we can see
that it has this section on pre processors. Now, as it mentioned, we can select our preprocessor
when we're creating the project, meaning when we ran that first Vue, create a project name, that
command would take us through setting up SAS automatically. Now, since we did not choose
SAS back, then when we were setting it up, there are ways of adding these packages, which
you can do through this command, npm install, and then installing the sass loader. And also the
sass package. Now, if I scroll down a little bit, it is giving me this note about Webpack
four, which is what I'm using in vcli. Four, I have to make sure I have a compatible version
of these loaders. So I am going to go ahead and grab this npm install command where I can install
sass loader at a specific version and also sass and installed those packages for me. Now I
should be able to run my server once again. NPM run serve. Now it is complaining that I don't
have one specific CSS module, because I haven't installed it in my node modules. But that is
actually a good sign because that means that it is reading through the rest of my file here,
it's reading through this, getting to this line and saying, Hey, I can't find that file. So I'm
just going to comment that out for right now. And now we have one more error here. And
that is it's looking for images that it can't find right now. Let's go ahead and
resolve those. And they're coming from this file. So if I go to splash dot sass,
now you'll notice the syntax is a little bit different here. You can basically think of it
as just an indented syntax without curly braces. Either way, you can see that the attributes are
the same here. So I have a background image, it's looking for this image. And again, there's a
background image, which is looking for this green image. So I'm going to create an images folder
here, an IMG folder, and put those two images inside of the IMG folder, and then update
this path. So back in my old application, they were in my public directory, I have
green, and splash. I'm gonna copy those and paste them here. And I should be
able to reference the relative path here. close this file. And you can see I have the
styles for my main application in here. Now, let me do one more thing and get
rid of this boilerplate here. So I can be ready to put my own content
there. So let me get out of here. And go to source slash Vues and home, I'll
get rid of this image, also get rid of that component. I'm just going to put home here
for now and get rid of the component everywhere. Now if I go back to this page, you can see
that it is ready to add my own custom content. And I can see the Products page in navigates
as well. One more thing I'll go ahead and do is add a past orders page to the router at this
route. And all I have to do is basically copy the products route. This will be past
orders. I can call it past orders. Past orders. Now I need to create this
component. It's connected to my router. So I'm going to create it in the Vues folder.
Call it past orders that Vue and I have a shortcut snippet here. I'll show you To
use us and second, but if I click enter, it just created the template tag for me. And I'm
going to put an h1 in here that says, past orders. And now I have this page working. So all
three pages are there. In the next video, I'll be putting content on these pages, and then
hooking them up to JavaScript to be functional. Now, let's work on putting
actual content on this homepage. I'm in the original application. Now, let me go
to source inside of Vues here, I have my pages, actually, the main page is still in app dot
html. So I'm going to go ahead and grab these two container elements here, the div and the main
container, copy those, go over to my new code, my vcli project. And here, I can come to
my homepage, and just paste that in here. Alright, now take this, just the indentation, get
rid of that old word. And now I have my splash container. And also my main container.
And nothing is showing up on the page. So if I look in the dev tools, it says
cannot read property slice of undefined. And I can search for where that is being used. And
inventory dot slice. So of course, it is broken right now because I don't have any inventory.
So let me grab that from my original code base. If I go here, I can see in food dot JSON, this
file is really where I have my inventory items. So I'm going to copy this
file, copy, go over here. And inside of source, I'm just going to paste
that file. And now I need to import this into my Vue j s. So if I want this right now in my home
component, I need to import it at the bottom here. So let me import my data. So import food from
go up a directory food, that JSON. Let's set it equal to a data variable. So data and then I
can return. And then I can set inventory equal to food. Okay, let's try this out. And now we
see the banner displays just fine. And we can see our recommended Products section at the
bottom, which is already displaying real data. Because we already set this up. And this is
basically the same logic as with the other app. But we've only rewritten this
in a component structure. Now let's pull in the other pages really quick.
So we have past orders, and also products. Let's go to products. And if I go to the Products
page, I can just grab this main section here, go back over to my code, and then paste that
in. Now this page should work as it is because if I look at all of the code here, we never
made that dynamic. So that's something that we will have to change later. But this is
all hard coded. Let me grab the past orders page real quick. And then we can take a look at
it in the browser. So if I go to past orders, let me fold this main section. I'm gonna copy
this and go over here to my code. Paste that. And now let's take a look at these pages. Okay,
so our past orders page has an error. And it's complaining that this eye tag, which was used
for icons generally that it doesn't have a closing tag, meaning it's not explicitly self
closing and I not explicitly closing it either, like this TD dag here has a closing TD tag there.
So I'll have to fix that. That's just how Vue templates work. So let me search for I, and seems
like it's only in two places, which is good. All I have to do to fix that is
either I could do a closing tag, things like IMG and I and certain tags don't
really have closing tags. So all I have to do is make them self closing, since you're never
going to nest anything inside of this tag in general. So I'm just adding the forward slash at
the end. And I will do that with this AI as well. And that fixed my error. And
now here's the Products page. And the past orders page as
well. This is kind of a table Vue of previous orders. Now what about the sidebar?
Let's add that logic back in in the next video. In our original application, we had this
sidebar on the right to display our cart. In this video, we're going to move that
over to our new Vue see ally application. So I'm in the original code base here. If
I go to any of my files, I can see there's a sidebar component, which is a custom Vue
component that I define in my app dot j s file, this sidebar component that I register, and
I can basically use it globally throughout my application. Now, of course, this is just
regular Vue code. So I could absolutely do the same thing in my new application. But
there are other ways that I can now create reusable components. So I'm actually going
to put it in my components folder. instead. I'm going to copy all of that. Let me go to
components, I have this old HelloWorld component, I'm going to delete it because
I don't need it anymore. And then I'm going to create
a new file here and call this sidebar dot Vue. In here, of course, I need the
template. And I'm going to paste all of that code. And this is basically all of the cart logic.
Now there are a few things I will need to add, pass in a dynamic toggle here when the button
is clicked. So let me go ahead and set that up. Now the first thing I need to do is import
this sidebar component into my application. And it's going to be globally available
across all my pages. So I'm going to import it into my app dot Vue file. And I'll
do it below. Actually I do at the bottom here. I'm going to put sidebar, it has to be
of course self closing here. And also the convention is to capitalize custom components.
So you can easily see them and see they're even highlighted differently than anything that is
lowercase that I've pulled in from a library or that is just standard HTML. I'm going to get
rid of my style tag here and add a script tag. And now I can import that component. So I'm going
to import sidebar from that slash components slash sidebar dot Vue. Now another way of writing
this and what you'll see, a lot of times see in Vue applications. Instead here you'll see
an add sign. Now this is a shortcut kind of a reference to the source folder. So that way
anywhere in my application, no matter how many files deep my components are, I don't have to
do anything like dot dot slash dot, dot slash dot, dot, etc. I can always reference the source
folder with an at symbol. So it will be source slash components slash sidebar dot Vue. Now any
component that I import into another component, I need to register it and tell my
Vue application I'm going to be using this component. And I can do that by setting a
Component Object on this default options object in Vue. And I can set the sidebar component here,
registering it here or including it in the list of component notes here just means that I can use
it up here in my template. So how this works basically this whole object here, it's called
the options object. And any kind of JavaScript functions or data will get set on this object,
I just want to point out that this is the exact same as the options object you used in custom
components like this one, except the template in our dot Vue file is just included at
the top up here inside of this template. And if we look at this main app component here,
everything inside this object, all of this data, computed methods, all of this stuff is the options
object. But here we have it to be used globally. And when we create a vcli application,
we basically get one template, and one options object per component that we use
to define everything on. Now the thing about this is that each component only knows about the
JavaScript inside the options object of that component. So if I create a function here, I can
only use it up here and in no other component, unless I explicitly pass it into that component to
be used. Just the same way that we pass the data and functions around to different components when
we were building the static application. And here, we're going to need to do that, again, because
sidebar requires certain things to be passed in. Now, if we look, here, we can see
that first there is a V, if Boolean, there's a function to toggle the sidebar,
when it's clicked, or when the button is clicked to open or close it. There is also a cart
object for what is currently inside the cart. There are all of our inventory items,
and then there is a remove item function. So I'm going to copy all of these things and
paste them over here. And now I need to define these properties. The first thing is Vf, I need
to create a show sidebar data property here. And I'm gonna set this just default as true for
right now. So I can see the sidebar. Now I need a toggle sidebar function. Now, where does
this come from? It has to come from my app component up here, because I'm passing it in,
basically from app to the sidebar component. So here's my toggle sidebar function. And I'm just
going to grab all of these functions right now. And I'll create that methods object.
And I pasted in all of my methods here. Now, here's another tricky part because I want
to reference inventory here. But unfortunately, I only have it in my home component, which I
just kind of quickly put there to fix my issue of basically inventory being undefined. So I'm
going to have to restructure my application. So I'm not importing inventory separately into each
component. So let me actually take this import. And I'm going to just import inventory into my
app dot Vue component. So I'm importing it here. And then my logic here, so inventory food.
And I'm going to add that to that as well. So inventory is food. Now I need to get it to my home component. But it's not really a
registered component on this page, like sidebar, I can easily pass elements into sidebar as props,
because it's a registered component right here. But home is a little bit different because the
router is dynamically putting the home component there. So how do I pass props through the router
then, to whatever component the router loads, what we're going to do is pass in inventory
into basically any router Vue component. So I'm going to pass in the inventory
variable And of course, I need to V bind this to make it actually look for a variable, and
not consider it to just be a string here. So now I'm passing in inventory. And I need
to accept that in the child component. So instead of data here, I'm actually going
to have to use props just as I did before, and have a props object, or I'll just do it as an
array actually. And I have to call it inventory. There are few more broken elements that I will
have to fix here that the sidebar is expecting, I have my inventory and remove item. And
I really just need my cart at this point. Now, if I look in the original version, I
can see the cart is just an empty object. And then things can be dynamically added
to the cart. But we're going to worry about dynamically adding things in a minute. But
first, I'll just set it to an empty object. So let me go to data here and set cart to an empty
object. Really quick, let's go ahead and grab this computed property as well, because we will need
it. So I'll come down here and put computed. And let's check this out in the browser. So it's
complaining right now that it can't find this JSON file. And that's because we are
importing it from the wrong place. And yeah, the app is running products,
past orders, everything seems to be working okay. However, we don't have the sidebar yet. So
let me go ahead and uncomment, this code here. So we have toggle sidebar, and also showing
the quantity and the button here. So here, I should be able to see the button that we had
before in our previous application. Alright, when I come here, and refresh, nothing shows
up. So we have some kind of an issue. It says uncaught type error kept by path of undefined.
So the path, this is referring to the router. So I think it's giving us an error in the router
link, because we are not properly using the router link. So let me just change this to a div, we
basically aren't telling it to route anywhere, we are just using it as a clickable element.
So we might as well be using something else. And now it is working. Except I can't click
on the cart button that's not working yet. But everything else is working. Let me
scroll up to see my original error here. So it says cannot convert undefined or null to
an object. And this loop is basically inside of my sidebar component. So it's
complaining about this line here, line 25. I'm trying to loop through a cart object,
get the quantity and key as well as the index. And basically it's saying that cart must be undefined
value. So let me take a look in my app here. It's not opening. So let me actually
take a look at the original code. And inside of my app dot j s, I
have all of this code moved over except this mounted here, but I don't need
that anymore, because I can now directly import the JSON file. I don't need to fetch it.
So here's my sidebar component. And actually, I didn't copy over any of the methods here
and I'm also forgetting to add in the props. So let me go ahead and do that. Just
copy this. Go back here to sidebar and I do need a script tag at the bottom here. So
I'm going to add a script tag, paste in the props. And then I also want the methods from
here so I'm going to grab those as well. Now calculate total and get price are defined
Then I also have all of the props here. So let's see if this works. Yay. And the toggle is
perfectly working. Of course, it's starting off as open. If I refresh it, it just automatically
opens. So let me change that in app dot Vue. I'll come here and say show sidebar is false.
All right, let me see if we can use this. So it's not dynamically adding items to the
cart yet. So we will fix that in the next video. In this video, we are going to hook up
the add to cart functionality so that when we add to cart here, it will show up in the
sidebar. If I look in the terminal, right now, you can see that this add to cart,
it's saying it's not a function. So I'm getting an error when I click this Add to
Cart button. Now I can see why I'm getting that, because that is in my homepage component.
And if I go down here, I can see this add to cart function that I'm calling when I click that
button is not defined anywhere in this component. Where is that function defined? It is
in the app dot Vue file. So if I go to my methods, I can see I have an Add To Cart method
right here, I basically need to pass this function into my homepage for my homepage to be able
to use. So I'm going to also pass that through the router, as I did before. And then in my
homepage, I can also receive that as a prop. add that on to the props list, add to cart. So I
should have access to the function that I passed into this home component now through the router
Vue. And let me refresh and see if this works. Add To Cart. And you can see that the function is
working because the quantity changed down to zero. The cart says two items. And if I open it,
it does indeed list two items here. Now, why are there forward slashes here,
we can actually see in the homepage, that in regular JavaScript, this is actually in
the sidebar component, that in order to put $1 sign before the variable we needed to escape
it. But we don't have to do that in a Vue j s application. Because it's no longer in a regular
JavaScript file. It's in our Vue, j s template. So I can get rid of all of these escaping
characters. And now that looks much better. Now if I want to delete this, it deletes
I no longer have any items in the cart, I can add a couple items and I get items
in the cart. If I go to another page, the cart should still work. Because that
is a shared component that I can see across any page. In simple applications. This
type of data sharing works pretty well, we can keep all of our variables in a parent component.
So in this case, in our app dot Vue component, we pass functions and variables down to children.
And then children can call functions, like add to cart that will then update the state of the parent
component. Now in more complicated applications, we would need something a little bit more robust
for state management, and being able to share all of this data throughout our application.
And we will talk about that in a future series where we cover Vue x, which is Vue j s is default
state management library. But for right now, we are going to leave the application as it is
and work on it in future series and lessons. So we have the homepage, the cart sidebar. Now we
really need to hook up some of the information on this page. So the Products page And it's really
exactly the same as the product section. Here, on the homepage, we have all of the same kind
of cards and information. So since we have the same thing pretty much in multiple places of
the application, it makes sense to pull out all of this UI that makes up these cards into its
own component. And then we can share it across the application and on any page that we want.
So let's go ahead and create a card component. Now in components here, I'm going to create a
new file. And I'm going to call this product card dot Vue. I'll start with a template.
And now I'm going to go to my home page. And I can see there's a for loop here that is
looping through and displaying all of the cards. So I'm going to grab this whole card here
and paste it in my product card file. Now this is just an individual card. So I don't
need a for loop in here. Let me get rid of this logic. And this will just be one card. Now
I will need the product information for this card to display correctly. So I'm going to have to
accept that as a prop in my component. So let me create a script tag. I'll create props here, just
an array of props. And I'm going to say, product. So I accept the product props into my component.
And now I can use it in my template. Now, I can remove all of this logic from here. And the only
thing I need is actually to import that component. So I need to import product card from, I'm going
to use my source folder shortcut slash components, and slash product card dot Vue. And now I need
to register this as a component so I can use it. And now in my code up here,
I'm going to use product card. I'll clean up the lines a little bit here. And I need to make this self closing. Because
all tags in Vue templates need to either be self closing or having a closing tag.
Now I am no longer using this index here, I'm going to see in my product,
if I'm using the index anywhere. And I am indeed passing in the
index. So I will need to accept the index as a prop as well. Let me change
this to index that's a little bit more clear. And I will get index here. And
I'm going to pass that in here. Of course index is a variable, not a string, so
have to V bind that. And that should work here. Let's see if this works. And we are getting
an error here. Now that is because product is now a prop. And of course we cannot
mutate props from the parent component. So we can actually fix this by not
mapping to the product prop at all, we're actually going to create a local
variable inside of this product component. So each component each time we use the product card
component, it will have its own local variable. And we can do that by adding a data
prop here. And in the method, we need it return returns an object. And now we can
simply map quantity because each card only has one input box. So we'll just map it internally
in the card. And we can check that this works. Not sure why it only has two cards right now.
But let's try this. So I pressed the number two. And I can look in my Vue, j. s, Dev Tools.
And I'm getting an error here. And it says I can't read property name of undefined. So
product name. Yes, I believe I have forgotten to pass in the correct props here. So let me
add those, I need to pass in product equals product. And then while I'm here, let me
also add the add to cart function equals Add To Cart. There we go. And now let's check it
the page loads and the page is loading. Alright, so now we have all of the cards loading. And
let me just look, in my Vue dev tools, I can see all of my product card components. So let me
just take a look. If I change this to two, and I can see the quantity is two. If I change it
to 22, it's now 22. Alright, so that is mapping correctly. Now I need to get this quantity, the
value up through the home component to the app component, where I am actually performing
the function of adding it to the cart. So what I'm going to do, for right
now, I'm just going to pass in a third parameter, and I will pass in quantity.
And now let's take a look at our function, our Add To Cart function in the app component.
So we are adding items on to the cart, if they're not already there. And then we are
basically incrementing the number here. So now that we have that third parameter being passed
in, which is the quantity, all we have to do is changed this line to B plus equals quantity,
which is now getting passed in. And then of course, we don't need this line, because we
are no longer mapping to a nested quantity. Rather, we have the quantity variable right here.
This also means that we don't need to pass up the index anymore. So we can remove that from this
function. We only need the name and the quantity basically, so that we can add it to the cart.
Let's check and see if this works. If I come here, the number still maps to the
component. Now if I click Add to cart, it is not in my cart. Let's
see if we got an error. Add to cart is not a function. Let
me look inside of my home dot Vue. I have add to cart that I am getting from the
parent component. So from the app component, I'm passing that in to the product card. And I should
have it Oh right, I didn't accept it as a prop inside of the product card. So now
let's see if this works. Let me refresh and go into my Vue dev tools. And now I can see
it's properly working here. If I want to add 10 artichokes, and I have two radishes, and I have 12 items in the cart. Now my
rounding functionality isn't properly working, as you can see, but it is properly adding and
displaying the quantity and the total in the cart. But I don't just want this functionality on
the homepage. I also want it on the Products page. So let me import those components
into the Products page now. So if I come to my product stock Vue file, I
actually have access to inventory already in here. Because if you remember in my app dot Vue
Passing inventory and the add to cart function into anything displayed by the router Vue,
which is basically any of our pages here home, past orders or products. They're all connected
to our router. So let's accept those props in the Products page to start with. First, let me fold
up all of these cards, get them out of the way. So let me do a script tag, props. And I'm
going to accept inventory and add to cart. One more thing I need to do is import this product
card. So I'm going to go to the home component, and just copy this import
and paste it into product or into the Products page. And now I
need to define this as a component here. Product card. And this should be components not
component. And I also have one more error here, which this should be a capital P. And now if I
see if I highlight this, all of these highlight, let me take a look at what this error is here.
The product card component has been registered, but not us. So let's fix that. So I
basically have all of these cards here. For the different items that show up on
the page, I'm actually going to just delete all of these right now. And instead, I'm going
to add the product card. So if I go to home, I can take a look at my product card that
I'm actually using inside the template. And I'm just going to copy that and paste it
here. But instead of slicing at three here, let me just do the first six elements instead. Now
because we already have inventory being passed in, as well as the add to cart function, of course
inside the loop, we're taking care of the product variable, there's really no other state that
we have locally on the products component. So this should pretty much work out of the box
for us. Let's check here. And we can see that it does indeed loop through and display all
of the cards on the Products page. Now, let me add a couple of these items to the cart here.
And you can see the cart just updated with five. If I add few artichokes, let's add some cherries,
and some cabbage, carrots. everything right, we have 17 items in the cart now. And we
can see that it added all of these items. Now if I go to the homepage, I can still see 17
items in the cart. Because we moved to a single page application. All of our routing is handled
by the Vue JS JavaScript. And we are actually sharing state between components. So all of the
state for our cart lives in the app component, which is the parent component of all the
other pages, the home page, the product page. And that's why all of the items in the cart all
of the data that we save here, in our application, it stays no matter what page we navigate to.
And even though this is displayed, or this card is on multiple pages, you can see how have
you made it very easy for us to reuse the same code and the same template to loop through and
display wherever we wanted on the application. And that's basically how reusable components
work in Vue js. I hope you enjoyed this course. And you learned a lot about Vue js, learning it
on three different levels through this course. We started off working in a basic index dot
HTML file. And then we went on to a static site of grading it a little bit with some Vue
js. And then we moved on to using the Vue COI and creating a fully dynamic single page
application that we have here. definitely reach out to me if you have any feedback,
comments or questions about this course. You can find me on Twitter and pretty much
everywhere online as Gwen Faraday or at Faraday Academy. Have a great day and
I hope to see you in the next course.