Out-of-the-box support for Babel, TypeScript, ESLint, PostCSS, PWA, Unit Testing & End-to-end Testing.
The plugin system allows the community to build and share reusable solutions to common needs. Vue CLI is fully configurable without the need for ejecting.
This allows your project to stay up-to-date for the long run. Create, develop and manage your projects through an accompanying graphical user interface.
Instantly prototype new ideas with a single Vue file. Effortlessly ship native ES2015 code for modern browsers, or build your vue components as native web components.
Create a project:. This is the docs for Vuex 3, which works with Vue 2.
- If you're looking for docs for Vuex 4, which works with Vue 3, please check it out here(opens new window).
- Vuex is a state management pattern + library for Vue.js applications.
- It serves as a centralized store for all the components in an application, with rules ensuring that the state can only be mutated in a predictable fashion.
- It also integrates with Vue's official devtools extension(opens new window) to provide advanced features such as zero-config time-travel debugging and state snapshot export / import.
- Let's start with a simple Vue counter app:.
- It is a self-contained app with the following parts:.
- The state, the source of truth that drives our app;.
- The view, a declarative mapping of the state;.
- The actions, the possible ways the state could change in reaction to user inputs from the view.
- This is a simple representation of the concept of "one-way data flow":.
- However, the simplicity quickly breaks down when we have multiple components that share a common state:.
- Multiple views may depend on the same piece of state.
- Actions from different views may need to mutate the same piece of state.
- For problem one, passing props can be tedious for deeply nested components, and simply doesn't work for sibling components.
- For problem two, we often find ourselves resorting to solutions such as reaching for direct parent/child instance references or trying to mutate and synchronize multiple copies of the state via events.
- Both of these patterns are brittle and quickly lead to unmaintainable code.
So why don't we extract the shared state out of the components, and manage it in a global singleton?
With this, our component tree becomes a big "view", and any component can access the state or trigger actions, no matter where they are in the tree!
By defining and separating the concepts involved in state management and enforcing rules that maintain independence between views and states, we give our code more structure and maintainability.
This is the basic idea behind Vuex, inspired by Flux(opens new window), Redux(opens new window) and The Elm Architecture(opens new window).
Unlike the other patterns, Vuex is also a library implementation tailored specifically for Vue.js to take advantage of its granular reactivity system for efficient updates.
If you want to learn Vuex in an interactive way you can check out this Vuex course on Scrimba(opens new window), which gives you a mix of screencast and code playground that you can pause and play around with anytime.
Vuex helps us deal with shared state management with the cost of more concepts and boilerplate.
It's a trade-off between short term and long term productivity. If you've never built a large-scale SPA and jump right into Vuex, it may feel verbose and daunting.
That's perfectly normal - if your app is simple, you will most likely be fine without Vuex. A simple store pattern(opens new window) may be all you need.
But if you are building a medium-to-large-scale SPA, chances are you have run into situations that make you think about how to better handle state outside of your Vue components, and Vuex will be the natural next step for you.
There's a good quote from Dan Abramov, the author of Redux:. Flux libraries are like glasses: you’ll know when you need them.
We worked for 9 months on Nuxt's new server engine for Nuxt: Nitro.
It unlocks new full-stack capabilities to Nuxt server and beyond.
In development, it uses Rollupand Node.js workersfor your server code and context isolation. It also generates your server API by reading files in server/api/ and server middleware from server/middleware/.
In production, it builds your app and server into one universal .output directory. This output is light: minified and removed from any Node.js modules (except polyfills).
The output is combined with both runtime code to run your Nuxt server in any environment (including experimental browser Service Workers!) and serve you static files, making it a true hybrid framework for the JAMStack.
In addition, a native storage layer is implemented, supporting multi source, drivers and local assets.
The foundation of the Nitro server is rollup and h3 : a minimal http framework built for high performance and portability. At the center of every Vuex application is the store.
A "store" is basically a container that holds your application state. There are two things that make a Vuex store different from a plain global object:.
Vuex stores are reactive. When Vue components retrieve state from it, they will reactively and efficiently update if the store's state changes.
You cannot directly mutate the store's state. The only way to change a store's state is by explicitly committing mutations. This ensures every state change leaves a track-able record, and enables tooling that helps us better understand our applications.
We will be using ES2015 syntax for code examples for the rest of the docs. If you haven't picked it up, you should(opens new window)!
After installing Vuex, let's create a store. It is pretty straightforward - just provide an initial state object, and some mutations:. Now, you can access the state object as store.state, and trigger a state change with the store.commit method:.
In order to have an access to this.$store property in your Vue components, you need to provide the created store to Vue instance.
Vuex has a mechanism to "inject" the store into all child components from the root component with the store option:. If you're using ES6, you can also go for ES6 object property shorthand notation (it's used when object key has the same name as the variable passed-in as a property):.
Now we can commit a mutation from component's method:.
Again, the reason we are committing a mutation instead of changing store.state.count directly, is because we want to explicitly track it.
This simple convention makes your intention more explicit, so that you can reason about state changes in your app better when reading the code.
In addition, this gives us the opportunity to implement tools that can log every mutation, take state snapshots, or even perform time travel debugging.
Using store state in a component simply involves returning the state within a computed property, because the store state is reactive. Triggering changes simply means committing mutations in component methods.
Here's an example of the most basic Vuex counter app(opens new window). Next, we will discuss each core concept in much finer details, starting with State.
You are reading the documentation of Vue Router 3 for Vue 2.
If you are working with Vue 3, use the Vue Router 4 documentation(opens new window) instead. We will be using ES2015(opens new window) in the code samples in the guide.
Also, all examples will be using the full version of Vue to make on-the-fly template compilation possible.
See more details here(opens new window). Creating a Single-page Application with Vue + Vue Router feels natural: with Vue.js, we are already composing our application with components.
When adding Vue Router to the mix, all we need to do is map our components to the routes and let Vue Router know where to render them.
Here's a basic example:. By injecting the router, we get access to it as this.$router as well as the current route as this.$route inside of any component:.
Throughout the docs, we will often use the router instance. Keep in mind that this.$router is exactly the same as using router.
The reason we use this.$router is because we don't want to import the router in every single component that needs to manipulate routing.
You can also check out this example live(opens new window). Notice that a
You can learn more about it in its API reference.
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.
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.
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.
They are basically a way to connect elements in our HTML or template here with the Vue j.
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.
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.
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 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 now I should be able to type in something here, this has to be an email.
So I'll say [email protected]
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.
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.
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.
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.
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.
So we're going to do this in Vue, j.
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.
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.
It's called a template string.
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.
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 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 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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
And now import this file into my HTML.
And you can see my page is still working.
My cart is still fully functional.
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.
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.
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.
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.
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.
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.
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.
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.
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.
All of these dot Vue files are parsed by the Vue and web pack setup, that the Vue COI 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.
So generally, that would be this main.js file, what I can do is import from assets, styles.
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.
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.
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.
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.
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 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.
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.
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.
But we don't have to do that in a Vue j s application.
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.
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.
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.