Vue.js Tutorial: Beginner to Front-End Developer

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] thank you UI Frameworks have drastically changed the way that we write web applications and I get it there are many Frameworks to choose from and picking one much less getting started with it can be daunting well let me make it a little easier for you while react has the benefit of name recognition there are other Frameworks that in my humble opinion do a much better job for example vue.js is extremely approachable if you already know a little HTML CSS and JavaScript its feature set is easier to understand and use it's very very fast and its growing Community is ready to jump in and help if you have any questions hi I am Jeremy McPeak and I'd like to teach you everything that you need to get started with vue.js we'll start at the very beginning and I'll teach you the fundamentals using just The View Library no build tools or tool chains required you'll learn how to create applications Define and use options and organize your applications into smaller more maintainable pieces called components but then we will jump into the tool chain because it makes working on larger projects easier you'll learn how to load and work with reactive data how to handle user input and create custom events that you can use in your applications I'll also teach you how to manipulate style create computed properties and Define objects that watch your data for changes so that you can react to those changes you'll learn how to create single page applications using the view router and how to use the composition API to improve maintainability we have a lot of ground to cover so when you're ready queue up the first video and we will get started but first if you're looking to create a professional website or you want to add features to make your website stand out then head over to codecanyon the marketplace for high quality JavaScript and PHP components HTML5 and mobile templates and so much more the items at code Canyon can help you easily add the functionality and eye-popping visuals that you need to meet your business's goals you'll find a massive library that contains thousands of JavaScript and PHP components and almost 20 000 HTML and mobile templates needless to say you'll find what you're looking for to take your site to the next level there are two things that I want to touch upon first is your code editor now technically we are working with text and we can use any text editor to do the work that we need to do however the text that we are working with is code and code editors have features that make it easier to work with code so I recommend using a code editor there are many free and many that are not free so feel free to use whichever one that you are comfortable with I personally use Visual Studio code because it's free it's also cross-platform and it is also the best code editor for JavaScript but again feel free to use whichever code editor that you are comfortable with the second thing is the view Dev tools now these are tools that you install within the browser they are used for debugging and you will see me use them throughout this course in fact if you look in the upper right hand corner of the browser you can see that I already have them installed it's this view icon up here and I recommend that you install this as well of course Firefox Chrome and well everything else is based upon Chrome so all of the browsers are supported by the dev tools so once again I recommend that you install them because they are very useful so as I mentioned it's very easy to get up and running with view so if we go to viewjs.org let's go to the quick start and there's going to be a section called without build tools now yes eventually we will get into the build tools because well it just makes our lives a little bit easier but for right now let's go to the section without build tools and let's copy this first line This is using the CDN which is what we are going to do so let's hop on over to our code editor let's create a new file which I'm going to call index.html and as far as the title is concerned let's just call this view Basics and then let's paste in that script element let's also go ahead and paste in the CDN for bootstrap just so that we have things that don't use the default style sheet and let's start with just some content that we're going to hard code into this page and eventually we are going to use view to generate this content for us so we'll start with an H1 this is the title of our page so let's just say hello View and then we will have some content such as welcome to the wonderful world of view and then let's open this up in the browser we can just double click on the icon we aren't making any HTTP requests or anything like that so this is going to be fine and there we go that's great however I want to add some styling here so let's actually wrap this in a div with a container class so that we can use bootstrap there and as we refresh okay that got moved over but that's okay so we want to use view in order to essentially provide this same content and we can do that by adding a script element to the bottom of our body because we want this to execute after everything else has been loaded and we are going to create a View application by using the view object this is given to us by The View library and we have a method called create app now I said that this is creating an application which hello it's called create app but this also creates what we typically call A View instance and one of the really cool things about view is that we can have multiple view instances within a single web page which is something that we will look at in the next lesson but for right now we're just going to work with one little application and we want to mount this somewhere within our web page and we do so with the mount method and then we specify the HTML element where we want to mount this and well we want to mount this inside of our div element now this is a CSS selector and right now we only have one div element so this is going to be fine however I think that we would be better served if we have some kind of unique identifier here so let's just call this content and so we will change our CSS selector to the ID of content now if we view this in the browser it's going to look exactly the same there's nothing that's going to be different and that's primarily because yes we created a view instance but it's not really doing anything however there's one very important thing that has happened behind the scenes and that is since we have mounted our application with this element with an ID of content what we have inside of here is actually a template and view is going to use this template in order to generate what we see inside of the browser now of course right now our template is hard-coded HTML but we want to soft code this we want to provide the data to our applications so that we can view them through our template so we do this by passing what we call options to this create app method the options is nothing more than an object and the properties are well they're different options the first one that we are going to look at is the data option this provides data to our application it is a function that returns an object now if you're familiar with react or other Frameworks this would be referred to as State this is the state of our application so we essentially have two things that we want our application to work with the first is the title of the page that string of hello view so we are going to you call this page title and let's just go ahead and take that text we'll cut it out of our template and we will paste it as the string for our page title so let's hop on over to the browser let's refresh and of course we see that change but of course we want to display that page title so we need to tell view where to display our page title within our template we do that with a pair of curly braces and then inside is our data property page title so if we go back to the browser and refresh we see Hello view let's do the same thing for our content and let's just call this content so we are going to use the templating syntax to Output content now if we don't specify a Content data property and we refresh the page well of course we don't see anything because we did not supply anything for the content for our application if we pull up the browser's developer tools we will see a warning that the property content was accessed during render but it is not defined on the instance so essentially what that means is we've used content inside of our template but we didn't Define it within our application so that's easy enough to do we just need to add a Content property to our data and now whenever we go back to the browser let's refresh we of course see the content that we would expect to see and the console does not have that warning anymore so we have now created our first View application we did so by using the view object and calling create app this created a view instance we supplied an options object that defines the data that our application is going to use we have two pieces of data we have the page title and the content we are mounting this application to an element that has an ID of content and in our template we are defining where we want to display our applications data well in the next lesson we are going to add another view application this will be one that will control the navigation for our web page in the previous lesson we created a very simple application to display some content within the web page this application has two pieces of information or two pieces of data the page title and the content and we mounted this application in an element that has an ID of content which is this div element inside of this div element we have our templates where we specify where we want to display the page title and the content so in this lesson I want to expand upon this I want to create a new View application now this doesn't mean that we have to create another web page we can have as many View application is inside of the same page that we want and sometimes we want multiple applications sometimes we don't in this lesson we are going to create an application that is going to control the nav of our web page so I'm going to paste in the markup for our nav bar this is just a typical bootstrap nav bar if we go and look in the browser there we go we have the navbar brand which is just my view and then we have a single link of home if you're not familiar with bootstrap if you wanted to add more links to a nav bar there is this unordered list and each list item is going to be an item in that nav bar so here you can see that that is the home link and if we wanted to add links for let's say about in contact we would need to replicate that same markup change the text and of course we would also want to point to a different href we'll get to the href later for now I'm more concerned about generating the content of home about and contact so we've done that with some hard-coded HTML let's use view to do that so let's start by creating a new application we're going to go ahead and pass in our options object where we are going to Define our data because our data is going to define the links that this particular View application is going to generate so let's have a property called links which is going to be an array and for right now we're just going to work with simple strings so that we will have home about and contact of course we need more information if these were going to be actual links which we will get to that at a later time for right now though this is going to be fine and we want to mount this application to our Nav Now for right now this is okay because I don't intend to have any other nav elements inside of the page however if it does turn out that we have multiple nav elements then we would need to use something a bit more unique but this is going to be fine and so now that we have mounted this application to our nav element that means that inside of the nav element we have our template and we can Define where we want to essentially display the text for our links which are of course home about in contact so one of the ways that we can do that is well like this we can use the links array and then specify the index of the value that we want to display so home is index 0 about as index one contact is index two and of course if we view this in the browser we aren't going to notice any differences in the navbar but that is a horrible way of going about this because our links are in an array and anytime that we work with an array we typically want to use a loop now if this were just normal JavaScript we could do this in a couple of different ways one of them would be to use a 4 in Loop so that we could say four link in links and then inside of that for Loop we would use the link in order to reference the value of home about or contact well we can essentially do the same thing with view except that we don't do it inside of our JavaScript instead said we do it inside of our template we use what's called a view directive a view directive starts with v Dash and then there are many different directives in our case we want to use a loop more specifically we want to use a for Loop and it's going to look a lot like a 4 in Loop so that we can say for Link in links do this code and really it's more do this code so I want to be very clear here in that we are using the V4 direct this is a for Loop but we are using it on the l i element so we want to use this on whatever element that we want to repeatedly generate if we used V4 on the UL element then that would generate multiple unordered lists and we don't want that we want multiple Li elements so for each link in links we want wants to work with the individual link so when it comes to outputting the value we just use Link which is defined inside of our for Loop whenever we go back to the browser and refresh we see the same results now to prove that this is indeed generating the links from our links data let's change the text here so that we have home one about two and contact three if we go back to the browser and refresh home one about two and contact three now this is very very different from something like react where you would generate your elements with JavaScript and then output the results in the template view uses a very declarative syntax so that the goal is that you can read your template and understand exactly what is being output now in the next lesson we are going to take this a step further and generate some actual links so that we can navigate to different page Pages within our website in this lesson we are going to build upon the links that we created in the previous lesson because as it is right now well they're just basically text of course they are actual links because they have href values but it's set to a pound sign or a hash so we don't really go anywhere whenever we click on these links we want the user to be able to go to the home about or contact Pages now remember that our navbar is controlled by a View application and the links are generated based upon that application's data the data is an array called links which has just simple string values so if we want to generate actual links that go to an actual page we need something more than just strings we need really an object because an object can aptly describe a link it can give us the text as well as the URL that we want to navigate to so I'm going to change the links array so that it is an array of objects each object has a text property and it has a URL property now because I've changed this array we need to address our template because we were outputting just a simple string value with this link variable but now this is an object so we want to say link dot text because inside of the double curly braces we can use any JavaScript expression that we want if for whatever reason we wanted to Output one plus one we can do that because that is a valid JavaScript expression of course in the browser we're going to see 222 that's not very useful so let's change that back to link.text and if we take a look at this in the browser we are going to see the results that we had before home about and contact now view is a framework for building user interfaces and as a web page our interface is HTML CSS and JavaScript and when it comes to outputting HTML yes we can output text but there's more to it than just text we also need to be able to set the values of HTML attributes so because we used the double curly braces to Output text you might think that we would need to use that to do the same thing for the URL so let's give that a try let's make that change let's go to the browser let's refresh and let's pull up the HTML inspector so that we can see exactly what is being loaded in the browser and we can see well link URL inside of a pair of curly braces we see the exact string that we set for that attribute which makes perfect sense because this is an href attribute we need to tell our View application that we need to handle this a little bit differently this needs to be special so what we want to do is use a directive called V bind then we follow that up with a colon followed by the HTML attribute that we want to bind a value to in this case it's going to be href and then the value that we assign to this attribute is a JavaScript expression so we don't need the double curly braces instead we just need link URL so that whenever we go back to the browser we are going to see the results that we would expect to where the href is set to the URL property on our link object now binding data to an attribute is very very common so one thing that you're going to find in the majority of projects that you look at is something like this simply a colon because we bind a lot of data it makes sense to have a shorthand syntax to bind that data to an attribute so instead of actually typing out V bind colon we can just say colon followed by the attribute and we will get the same result and we can do this for any HTML attribute like for example this is a link and links should more often than not have a title attribute something that gives a description for the link so that we can have a description of this link goes to and then we can have like the home page or the about page but of course we need this to be dynamic because this is being generated dynamically well we can simply use V bind on the title attribute but remember that the value of this attribute is now a JavaScript expression so having just normal text is not something that we want because that's going to result in an error it's a syntax error because it's not a valid JavaScript expression instead what we want is to Output a string a dynamic string ring based upon the text of the link so I'm going to do this so that we will use javascript's string interpolation feature to Output a string that says this link goes to the and then we can use the text property on our link object and whenever we view this in the browser not only are we going to see the href attributes properly set but we will see the same thing for the title this link goes to the home page and if we take a look at the about and contact links we will see something similar the href is set to the appropriate value as well as the title attribute for each one of those links and so now whenever we click on these links if we had an about.html page we would navigate to that page the same is true for contact as well as home although I guess home should probably be index so let's make that change home will be index HTML so let's refresh the page home goes to index about goes to well what would be the about page contact goes to the contact page now there's one other thing and it's not that important right now because the data that we are providing our navbar is static we're not changing that data however when we do change that data view is going to automatically change what is seen inside of the browser we don't have to do anything view does it for us but we do need to help view so that it can identify which object that it needs to update so we need to provide a key or a unique identifier for each one of the LI elements that we are generating here with the V4 directive so we do that by V binding a key and this has to be a unique value for each individual Li element that is generated or a better way of thinking about it is a unique identifier for each item in the links array and one thing that is unique is the index of the elements in the array because the index of zero is forth home the index of one is for about the index of two is for contact so we could use the index as the key and we can do that very easily by modifying our for Loop so that not only are we going to be working with the link object but we also get the index of that element in the array so that's we can bind that to the key and from a user's perspective they aren't going to notice anything different this is strictly for helping view do its thing behind the scenes now in the next lesson we are going to transition this page into what's called a single page application basically it's a single page loaded in the browser and the content changes based upon the user's interaction so for example clicking on one of the links is going to change the content that is this displayed in the browser in this lesson we are going to turn our web page into a single page application and we can accomplish this in a variety of different ways using view however with everything that we have talked about thus far probably the most simple thing to do is to just combine our two view instances into one so that we have just one data object that we are going to work with which makes everything so much easier to do so this transition is going to be relatively simple all we need to do is take the data from one instance and put it inside of another so let's take the links from our nav instance let's paste that inside of the data for our content let's delete the nav instance and then we just need to change the CSS selector that we passed to the Mount method we can just pass in body so that we essentially Mount our view instance in the body of this application so this would cover both the nav and our content and so then the question becomes how do we need to structure our data because we need more than just a set of links and a single page title and content we need the link the page title and the content for each individual page that we want to display and we have three pages home about and contact so I think what makes the most sense is to essentially change our data into an array of pages and each one of these pages is going to be an object that has a link that has the text and the URL they have a page title and the content for that page now because we're making this change we do need to address our template especially when it comes to generating the links in our nav bar so we are no longer working with links instead we are working with an individual page inside of pages we can leave the index alone because we need to bind that to the key for our list of Li elements but everywhere else we used that link all we need to do is pre-pin that with page Dot and everything should work the same at least as far as the nav is concerned so let's do a sanity check let's go to the browser let's refresh and yes we have our links so now we just need to change the content that is going to be displayed whenever we click on these links so this means that we need to set up a click event for these links and this is very easy to do inside of view it might look a little wrong because it is somewhat reminiscent to Dom level 0 events now if you're not familiar with that terminology before there was any Dom specification the way that we set up event handlers was through HTML every HTML element had attributes like on click or on Mouse over or things like that that would let us set up an event on that element so for a click event we would have on click and then the value of this attribute would be some JavaScript expression that would execute whenever the user clicked on that element with view we use a view directive called V on we follow that with a colon and then we have the name of the event that we want to handle in this case it's going to be click if it was some other event like Mouse over or Mouse out or Mouse enter anything like that we would use just the name of that event but we would prepend it with the V on directive now there is a shorthand syntax instead of saying V on colon we can just use an at sign before the event name so at click is setting up the click event handler for this element I like to think of it as action and then click and then we just need to specify the code that it's going to execute whenever we click on this link whenever we click on a link we need to be able to track the link of the page that we clicked on so we need some other data property that we can use to track the active page and let's just call this property active page and it makes sense to initialize this as our home page so let's say that we're going to track this based upon the index so our home page is at an index of zero as far as the pages array is concerned so about will be index one and then contact will be index two so that whenever we click on these links we want to change active page to the index for the given page and so when it comes to displaying our con content we'll use Pages we'll use the index syntax so that we can use active page and then that will give us access to that Page's title as well as the content so another sanity check let's go to the browser let's give this a shot so let's refresh the page since home page is our default page we can see that that content is automatically displayed so let's click on the about link well we could see very briefly that the content changed but notice that we navigated to abouts.html that is the URL that was specified for that link and we don't want that because all of our content is now being loaded through JavaScript so we want to prevent the web browser from navigating to whatever URL is specified in the href and if this was just a normal Dom event listener we could do that using the event objects prevent default method but since this is view we have a more declarative way of doing that whenever we specify the at click directive we can follow that up with a DOT and then we can use this prevent modifier this essentially says that we want to prevent the browser from navigating to the href whenever the user clicks on this link so with that in place we can go back to the browser let's refresh the page now whenever we click on about we can see that the browser did not navigate to about.html but it did load the content that we specified and then whenever we click on contact well we see the same thing let's click on home home page contact about and we can keep doing this and it's going to work just like we would expect it to and this is one of the great things about Vue and really it's not just view but any UI framework like react angular svelt Alpine I mean there's quite a few these days but we no longer have to write the code that actually changes the content instead all we have to do is change data and then our application will react to that change in data like for example the only piece of data that we changed was the value of active page whenever we clicked on the link we changed that value and because of that very simple change view automatically updated the content that was loaded in the Dom because our code said to load the page title of the active page and to load the content of the active page and so this is where the power and the popularity of these Frameworks come from because we are no longer concerned with actually updating the Dom the framework does that automatically for us all we have to do is set up the UI to display the content that we want and then simply change the data or change the state of the application and view will automatically update the Dom for us when it comes to building Dynamic user interfaces there's so much more than just changing the content or updating content a lot of times we want to change or update the style that is applied to HTML elements like for example bootstrap gives us a class called active for our nav links so that we can signify to the user that the home link or the about link or the contact link is active it's just a visual cue that we can provide the user and as it is right now we aren't using that class because when we look at our markup all we have specified is the nav link class for these links what we want to do is include active but only when the active page is equal to the index of a given page so we need to be able to add some kind of conditional statement so that if the active page is equal to the index then we would use the active class you know if we were going to use the ternary Expression it would look something like that well we can do this very simply by using V bind but I'm going to use the shorthand on the class now this is going to look a little weird because not only do we use the class attribute this is the HTML class attribute but we are also going to use the V bind directive on class so you can think of this as I want to apply these CSS classes always to the element by using the HTML class attribute and then for classes that you want to apply conditionally you'll use the V bind so the Syntax for this is going to look a little weird because we don't use ternary expressions or anything like that instead what we have is an object and the properties of these objects are the CSS classes that we want to apply to this element so in this case we want to apply the active class and the value is going to be our condition statement so we want to apply the active class when the active page is equal to the index of this given page so let's just take a look at the syntax again because as I said this looks a little weird especially when you are expecting to use an if statement or a ternary or something like that so we are using the V bind directive on the class and we are providing an object where the property is the CSS class that we want to apply to the element and then the value of that property is the conditional statement that will determine if that CSS class is applied so with that done we can go to the browser we can refresh our page page and you can automatically see it's a little difficult to tell due to the styling here but you can see that home is a little bit darker than about in contact whenever we click on about again it's a little bit darker when we click on contact it's a little bit darker now we can make this much more Apparent at least in my opinion if we change it to a dark nav bar so I'm going to change the CSS classes from navbar Lite and BG light to navbar dark and BG dark if we refresh the page now we can definitely see that home is active if we click on about if we click on contact we can see that those are active and we can inspect these elements and we can actually see the HTML automatically update so here is the a element we have the class of nav link and active so keep your eye on that whenever I click on home it's going to automatically update the CSS class so that active is no longer applied to the link for contact but if we take a look at the link for home well there it is right there so this gives me an idea I want to be able to toggle the navbar from light to dark so let's do that we know how to do that now that we can bind CSS classes but we do need to be able to track if we are displaying a light background or a dark background so let's add another date of property and let's just call this use dark navbar so of course if this is true then the navbar will be dark if it's false then it will be light let's initialize it as false and this means that we are going to modify our HTML class attributes so that we aren't applying the navbar light in BG light instead we want to dynamically apply the appropriate classes based upon on the value of this use dark navbar so once again we are going to v-bind the class we're going to pass in an object things are going to get a little bit tricky here because the CSS classes that we want to apply use hyphens which are not valid in JavaScript identifiers however we can use a string as a property name we can also apply multiple classes at the same time so that it looks like this so that we want to apply navbar light and BG light when use dark navbar is false and then we essentially want to do the same thing for the dark version but when use navbar it's true so once again we will change these values to navbar dark and BG dark so this looks even weirder than before so let's just take a brief moment to talk about this syntax so once again we are by binding our classes but since these classes use hyphens in their name we can't use these as normal JavaScript identifiers so our property name is denoted with a string we're using two CSS classes separated by a space as the property name inside of the string and then the conditional value is not to use dark navbar so when that's false we use the like classes when it's true we use the dark classes so with that in place all we need is a button to click on so that we can toggle those classes so I'm going to add a form after the unordered list of our navbar links let's add a class of d-flex and inside of this form we will have just a simple button let's go ahead and set up the CSS classes so that we make this blend in with bootstrap so we will use the button clasp let's also use button primary we don't really need to specify the type but we do need to handle the click event so let's do that with at click let's go ahead and prevent the default since this is inside of a form you know off the top of my head I don't know what the default action would be so it doesn't hurt to add the prevent modifier to this event and what we want to do is change the value of use dark navbar so that it is equal to its opposite and with that simple change we can go back to the browser we can refresh the page the default is to show the light bar oh it would be useful to have some text wouldn't it let's say toggle navbar so now let's refresh the default is the light background if we click on the toggle nav bar that should change it to the dark and it does the active classes being properly applied let's toggle back to the lights nav bar once again the active class is properly applied and everything works as it should now let's do this let's make sure that it's going to work if we set the default value for use dark nav bar that's true and of course it will we wrote this so there it is by setting that to default to True our navbar is now dark everything else still works the same we can toggle this to the lights but I think personally I like the dark so I'm going to leave it like that in the previous lesson you learned about one of the ways that you can bind CSS classes to an element and yes I said one of the ways because when it comes to working with style in view you can apply style in a variety of different ways in the previous lesson we used an object where the properties were the CSS classes that we wanted to apply and then their values were a conditional expression that determines whether or not those classes are actually applied to the element in the next lesson we will look at how to use arrays now in this lesson I want to focus on this expression because while it works I'd make the argument that it's not the easiest to quickly read and understand what's going on instead what I want to do is extract this out into an object that we would then just reference here so we could call it navbar classes and that makes it a lot easier as we were skimming through this we could see okay navbar classes are being applied and then later on we can look at the actual detail inside of our code so you might think that we would need to Define this navbar classes object in our data and yes we can technically do that but it's not going to behave the way that we expect it to in fact it's not going to work at all but let's look at it not working and talk about why it doesn't work and then we will look at how we can make it work so the first thing I want to do is essentially turn this from two lines of code into four lines because I personally think it's a lot easier to read and understand if we do something like this so that each individual property is its own each individual CSS class it's just my preference but I don't mind writing extra lines of code if it means that I don't have to come back to it in three months and think what am I doing here oh oh yeah so this is our object now because we are inside of JavaScript now we are not inside of our template we do have to adhere to the rules of JavaScript syntax this use dark nav bar isn't just a variable it's a property inside of our application because well here it is it's defined right here inside of this object so we need to say this dot use dark navbar and so that is going to be fine we can save this we can go to the browser we can refresh and whenever we click on toggle nothing happens now it's not because that there's an error we can pull up the console and we aren't going to see any errors at all we will see this warning and the only reason why we are getting this is because this script is inside of the body tag and we've created a view app that's mounted to the body so we can see that this is being ignored so that's fine we don't care about that but as I I click on the toggle button there are no errors appearing in the console so it's not working because there's an error it's not working because we used our use dark navbar property because this code is initializing our application's data it's not setting it up to be reactive or anything like that it is simply initializing all of the values for these properties so that means whenever the code executes to create this navbar classes object it is using the actual value of use dark navbar but it would essentially be translated into this so that it would be not false and the next line will be not false which of course is true and then for navbar dark that would be false and so on and so forth so these are the actual Boolean values that are being applied to these properties and so there's nothing that Vue thinks that it needs to react to inside of the browser whenever we click on the toggle button the use dark navbar property is changing but that's not the problem the problem is that the actual Boolean value is being applied to these properties so the way that we can get around this is by using what's called a computed property it is simply a property that is evaluated on the Fly and we create computed Properties by using the computed option so we have an option called data which is what we've been using thus far now we are going to use the computed option this is another object where the properties are functions that will execute so this is where we will Define our navbar classes but this is going to be a function because this is a computed property it has to execute in order to generate its value value and all we need to do then is essentially lift this code from our data and we want to return that inside of this computed property so the way that this works now is behind the scenes view knows that use dark navbar is something that it has to react to and because we are using it inside of this computed property it will then automatically compute this value whenever use dark navbar changes so we can go back to the browser now let's refresh the page and whenever we click on toggle we see that that functionality is back so because we click on this button it changes the value of use dark navbar and because we used use dark navbar inside of this computed property called navbar classes it will automatically recompute this property it essentially calls that function to compute it it Returns the object that is then used to bind to the class on our Nav Now in the next lesson we are going to look at how we can bind CSS classes using an array and how we can get the same functionality without using a computed property in the previous lesson I introduced you to computed properties which are well they're properties that are processed or computed on the Fly and we used a computed property to simplify our template so that all we had to do was bind this navbar classes property and that just happens to be a computed property whose return value changes based upon the value of used Arc navbar and that's all well and good computed properties are a wonderful feature but we can also do the same thing without using computed properties because instead of using an object we can use an array to bind classes so the first thing we need to do is just Define an array and then the individual elements inside of that array will be the CSS classes that are applied to the element so for example if we wanted the dark nav bar we would have navbar dark has one element in the array and then BG dark would be the other one so we can hop on over to the browser refresh and voila we have that functionality but of course if we click on the toggle button that no longer works because we have hard-coded the dark CSS classes to our navbar now without writing really any extra code we can get away with doing something like this so that we would check the value of use dark navbar and then we would have a ternary expression so that if this is true then yes we would use those dark classes otherwise we would use the light classes and I know that there's you know other CSS classes that we need to apply I'm going to be lazy and not apply them all we need to see is that the background color will change so let's refresh let's toggle and we have that functionality again however one can make the argument that our templates could be a little bit cleaner I mean yes this is fairly clean but the more CSS classes we add the more of a headache it's going to be to try to decipher all of this now before we want to move on I want to note that this expression is for just one element in the array if we wanted to apply any other CSS classes and always apply them like for example navbar and navbar expand LG we could do that just fine in fact let's go ahead and do that why not so just as a sanity check let's go back to the browser we will see the same functionality that we got before all of the static CSS classes are still being applied because this would look very different but we can still toggle between the light and the dark but I want to do something not necessarily fancier but it would be cool to do something like this to where we would have our individual elements but then we would have like a theme property and then we would change the value of that theme so that the nav bar and the background colors would change based upon that theme but of course everything else would be fine now this gets us away from using this computed property so let's go ahead and delete that this also gets us away from using this used dark nav bar instead we would have a property called theme to where we could initialize it as light or dark really doesn't matter let's go ahead and let's start with light let's refresh oh there's an error somewhere it's probably a syntax error and there it is right here inside of my template it I need to have that closing back tick so let's go back let's refresh looks like a light nav bar if we change theme to dark you will see the dark nav bar there we go so now we just need to write the code that's going to change the value of theme now we can do that like we've done for the use dark navbar property in that whenever we click on the toggle button we could do something like this to where we will assign a new value of theme based upon what its current value is so that if theme is light then we want to change its value to dark otherwise it's going to be light and that is going to give us the functionality that we are after however once again I would make the argument that this complicates our templates now we have to decipher that wouldn't it be cool then if we could just have like a function that would execute because in a real world application that's typically what we would do to begin with so we could have a function called change theme that we would call whenever the button is clicked so let's do that we just need to add a method to our application and we do so by using another option it's called Methods and inside of the methods objects are all of the methods that we want to Define so in this case we will have the change theme method let's start by creating a local variable we will initialize it as light and then we will check the current value of our theme property if it's like then we are going to set that theme variable to dark otherwise the current value of theme is dark and we already have light assigned to themes so that the final line of this method is simply going to Define our theme property the value of the theme variable so let's go to the browser let's refresh the page let's click on toggle and we see that we have the same functionality and of course we can change the value of theme from dark to light so that the nav bar will start off as light and then whenever we click on toggle it toggles it to dark so one thing you're going to find not necessarily with view but just any framework at all because all of these Frameworks are based upon JavaScript and when it comes to JavaScript you can accomplish the same thing in a variety of different ways just like here we have accomplished the ability to toggle our navbars theme in three different ways we've used computed properties we are now using arrays and methods and then we had an approach that didn't have anything we just had a somewhat complex expression inside of our template and so just like JavaScript where we have several different ways that we can do the same thing just because because we have different ways doesn't necessarily mean that one way is better than another it's all going to boil down to the situation and what makes most sense to you our application is very simple but it's also becoming a little unruly because we have all of this code just kind of thrown together and if we took the time to study this application we would essentially find two distinct pieces we would have the nav bar and then we would have the content and if you'll remember whenever we started this journey in view we essentially separated those two things we had two view applications one for the navbar and one for the content in reality it really doesn't make sense to have two separate applications because they are related in some way they are using the same data at least as far as the active page and the pages now however theme and the change theme items are specific to the nav bar so it still does make sense to separate these two pieces but we don't want to create different applications instead we will use what are called components and you can think of a component kind of like a little mini application inside of a larger application is so that we can make our applications easier to write and maintain but it's also so that we can extract functionality into a smaller piece that is specific for that functionality like for example the nav bar can be its own component and it would be responsible for doing whatever the navbar does and only what the navbar does so in this lesson we are going to create a component for displaying the Page information because this will give us the opportunity to talk about a lot of the fundamentals so that in the next lesson whenever we create a component for the nav bar we can go into some more complex topics so we want to create a component for our content the first thing we need to do is create a variable for our application because we need to reference our application in order to create a component and we need to do that before we Mount this so we're going to separate these into two statements so that we create our app and then we will Mount our app and before we Mount the app we want to create our component and we do so with a method called component the first argument that we pass is a string name for our component now there are some conventions that we need to follow here it needs to be lowercase and if it's just a simple word like page then we just call it page it also helps to not be an actual HTML element as well but this is something I was called page content or page viewer so if you have multiple words then you will want to separate them with a hyphen or a dash now the second argument that we passed a component is an options object so all of the ideas and Concepts we've talked about thus far such as data computed properties methods all of those are options all of those can be used inside of a component and the option that we are going to start off with is called template because remember an application needs a template and as I mentioned a component is kind of a little mini application inside of our larger application so we're going to take the markup that we have for displaying our content let's take that out of the body and we're going to use that as the template for this component now we don't necessarily need this ID attribute so let's get rid of that we haven't needed that for a while and as it is right now if we tried to use this we would run into an error because this component is trying to use the pages from our application and by default it doesn't have access to that information because it is now inside of its own component so for right now let's get rid of where we are outputting this data and let's just have some placeholder text so that we have page title and then page content and then we will use this component inside of our application and we do so as a normal HTML element except that it's not HTML this is a view component so we have an opening and closing tag and whenever we go to the browser let's refresh the page and we will see page title and Page content so that's working just fine so now we need to supply information for the page viewer to do its thing it is responsible for displaying the page title and content so we need to pass data kind of like we would pass data to a function except that in view we use the term props so a component has props that we pass data to and we can pass data in two different ways the first is going to look like just normal HTML attributes except that they are going to be specific for these components so we can say that we would have a prop called page title which is just going to be a simple string so we could have page title like that and then we could also have page content and once again notice how I'm typing these out they look like normal HTML attributes so that they are all lower case if they are multiple words they are separated by hyphens and I will have page content here and let's have something different so that whenever we view this in the browser we will see the difference there so we have these two props and that's great but it's not enough to just Supply values to them we have to Define them inside of our component so this is another option that we will specify and it's simply called props and it is an array that contains the name of the props except that here we are going to use camel case so we have page title and Page content so when it comes to our markup we use what would be typical markup attributes but when it comes to JavaScript we use camel case so now we can use page title and Page content inside of our components template so that we will have page title and then page content and whenever we refresh the page we are going to see our title and content change based upon the data that we passed to those props so this is the first way we are passing just simple string values and it's important to remember that distinction because we can also use the V bind directive with our props in which case we are binding some JavaScript expression too but as you know we don't have to say V bind we can just use the shorthand which is a colon so in this case if we wanted to use a string value we would have to surround these with string delimiters which in this case are just simple single quotes we refresh the page we see the same result but we want to be dynamic here so that's we display the title and the content for the active page so this is going to look somewhat similar to what we had before except that now we are passing this information as robs so whenever we go to the browser we are going to see the same functionality that we had before home page about and contact that's great however I think that we can make this a little bit better so that we have just a single prop that we can call Page and then we will pass in pages with the index of active page so that inside of our components we would then use the page title and content properties so whenever we use page viewer this is all that we have to supply and then we just need to update our page viewer component so that it has a page prop and it is going to display the page title and then the page content so just for a sanity check go to the browser refresh everything works exactly as it did before and so before we move on to the next lesson let's just go over the key things about creating components because this is important our applications are going to be full of components so we create a component we give it a name and that component can have options one option is the template another option is called props props are essentially the arguments for this component so that we can pass data to our components so that they can do whatever they need to do in the case of this page viewer it is simply outputting data so we have a prop called page we pass the active page as the page prop by using V bind so that inside of the components we can use that as an object to Output the page title property and the content property and so in next lesson we will create a component for our nav bar in the previous lesson we extracted the functionality for displaying the Page information that is the title and the content into its own component called page viewer it has a prop called page which we pass in a page object so that it can use the appropriate properties to display that information so now we essentially want to do the same thing for our nav and so let's just get started with the concepts that we talked about in the previous lesson I'm going to start by cutting out the markup for our navbar so that we can go ahead and Define that component and then use that markup as the template let's call this simply navbar and then the template is going to use backticks in order to delimit this string however we already are using the JavaScript template strings inside of this template so that means we will need to escape those which is simple enough to do but it is a pain and this is one of the reasons why when you start getting into components it makes a whole lot of sense to start using build tools and Tool chains because when you start using jsx you don't have to do anything like this but thankfully there's not a whole lot of escaping that we need to do here so there's our template and since we're here we can go ahead and Define the props that this nav bar is going to need because it needs the pages so that it can generate the a elements for the links it also needs the active page so that it can properly apply the active CSS class so let's define those props now technically we can call these anything that we want because remember that props are a lot like the parameters on a function these are variables that we will use inside of our template bullets however if we call them something other than pages and active page then we will need to make the necessary changes inside of our template and I don't want to do that so there we go we have our navbar at least the beginning of our nav bar so let's go to the body or to the markup of our application and let's use our nav bar and we will go ahead and bind the pages to the applications Pages array as well as the active page now this is very important because if we don't bind active page then we're going to run into some issues first of all if we don't then what we are passing is a string literal of active page which of course is not going to work at all but let's just imagine that by not binding active page we are still using that numeric value which is initialized as zero so one thing to remember is that data flows from parent to child so in this particular case the app is the parent the child is the navbar component so the data active page which initializes as zero is passed down to navbar so the next time that active page is updated that change is not going to be passed down to navbar because it is not bound so if active page becomes one well we essentially passed the value of 0 to it and it will stay as zero so if you want the child components to update based upon the data that it has been provided then you need to bind the data to those props so we want active page bound to the apps active page now there's a couple of other things that we need to do the theme is specific for the navbar so we can take that out of the application and we can Define that as part of the data for the navbar which this is just like the data option in the app it's a function that returns an object so there we will define theme the same is true for our methods because change theme is really only specific for the navbar so let's cut that out completely and let's add that methods option to the component so with that done let's go to the browser let's refresh the page now we're going to see that toggle works that's perfectly fine and I'm going to make it dark because it makes it easier to see what's going on here so I'm going to click on about nothing happens I'm going to click on contact nothing happens going to click on home and of course home is already loaded but nothing really happens and the reason is very simple and it's because we aren't updating active page now if we look at the template for navbar whenever we click on one of these links there it is active page equals index and active Pages being supplied as a prop but here's the thing props are read only so we can't change their value inside of a component now that makes perfect sense when you start thinking about how data flows as I mentioned it flows from parent to child so if we were to change the value of a prop inside of a child the parent would not know that the value changed because data flows from parent to child so then the question becomes how do we do the reverse how can a child notify a parent that something changes well it's very simple we use an event or rather we use what is essentially an event like for example we've talked about the click event before to where we say at click and then we have the code that's going to execute well in this particular case click is essentially a prop it's a special prop because it is an event but we can essentially do the same thing so that we have a prop that will execute and we can call this simply nav link click so that we would have a function that would accept the index so that we would change the active page now remember that since this is the navbar components we are now inside of the app we aren't inside of the nav bar so this code here is specific for the application but all we need to do is set the active page equal to index and we need to make that active uppercase p page so that's inside of our components all we need to do is change where we click on the a element well we need to do two things first of all we need to say that we now have a prop called nav link click and that this is a function that is going to execute and we will pass in the index so it works a lot like an event so the parent is supplying the function to nav link click that the child is going to execute it's going to pass the index back so that's inside of the application we can update active page to that index value so with that done we can go back to the browser we can refresh let's toggle that to Black so that we can see and we're going to see that this works exactly as it should so home of course is the default we see that we also see that home is active whenever we click on about home is no longer active about is active then of course we see the content for about whenever we click on contact I mean I hate to do a play by play here but this is the exact functionality that we would expect except now we have our application broken up into two different components that are responsible for their own functionality the page viewer is responsible for displaying the Page information the nav bar is responsible for generating the nav bar keeping track of the theme as well as notifying the application when the user clicks on a link and so in the next lesson we are going to get started looking at the view CLI which is the tool chain that makes it easier to build view applications and view components since the beginning of this course we've used Nothing But The View Library to go over the fundamentals and I wanted to do that because I want you to know that you can build view applications using just the library you don't need tool chains you don't need build tools you don't need anything except the View Library a text editor and of course a browser however we do have tool chains and build tools specifically because they make our lives as developers easier and while they are extremely useful for building large applications you can use these tool chains for building any size of application I always reach for the build tools just because it makes our lives easier so what we are going to do is install what's called The View CLI CLI stands for command line interface and it gives us all of the tools necessary for building our view applications but we also get to use features like jsx which is Javascript and XML as well as newer features to JavaScript so things that aren't natively supported by the browser really doesn't matter because the build tools are going to handle that for us and translate it into things that the browser understands but in order to install the view CLI you need node.js and if you don't have this then now is the perfect time to do it because it's not used just for view it's not used just for react or anything this is how we manage our dependencies node and more specifically node package manager is just part of modern web development so if you don't have it Now's the Time to get it just go to nodejs.org and download the LTS version the version number doesn't necessarily mean anything from our perspective now if we were going to build node applications yeah the version number matters but that's not the case just look for LTS that's long-term support and download mode and install it it is a straightforward installation just take the defaults and once that's done you will want to go to the command line because npm is a command line tool and we want to install the view CLI so it's at view then slash CLI and we want to install this globally now the reason why we want to install this globally is so that we can use the view command regardless of what directory we are in and we will use the view command to create our first project so let's call this view start spa for single page application we are essentially going to recreate the page that we've been building over the past few lessons but we're going to use the view CLI and this is going to give us several options that we will need to go through now I have some presets already done because as I said I use view so let's go down to manually select features and we want to select Babel because that is a compiler that allows us to use new JavaScript features in browsers that don't support it Babel will translate that into JavaScript that the browser does understand so we do want Babel and if we wanted to use typescript we could do that as well we aren't we're going to use just normal JavaScript now I'm going to uncheck the linter slash format just because that adds a little bit of extra stuff and I want things to be nice neat and clean now of course in a real project I would probably check the linter just because that's a good tool to use but it does also take some processing time and since time is of the essence we're going to leave that alone so Babel is really the only thing that I want to use right now so let's hit enter to go on we get to choose the version of vue.js the latest is 3.x and then we get to choose how we want our config to be laid out do we want them in dedicated config files or inside of the package.json we want dedicated config well I want dedicated config files and we can save this as a preset I'm not and so this is going to build our project and when the project is ready we want to CD into that new folder and then we'll fire up our code editor so that we can take a look at the project because this is going to be very different from the single HTML file that we've been working with thus far the first is going to be this public folder now this is well it's the public folder this is what the end user would see if they go to our application this is also a place where we can put our static files like images and things like that however there are alternatives to that approach which that is something we will talk about at a later time now you'll see that there's two files there's the fave icon and there's also index.html and there's not a whole lot here inside of the HTML file but do notice that there is this div with an ID of app this is where our application is going to be mounted now we can change that because we have complete and total control over our application but this is convention we'll just stick with this and notice that there's also this comment that says that built files will be automatically injected now for the vast majority of time in this course we are going to be using the development mode which is essentially going to build our application as we develop it and any change that we make is going to automatically be reflected inside of the browser so those files that are being built behind the scenes are going to be injected here so we don't have to worry about any of that it's just done automatically for us so that's the public folder but then there's the source folder and this is the folder that our source code lives the entry point of our application is this main.js you're going to see that the create app method is being imported into this file from The View Library it's also importing uh this thing from a file called app.view This is a component which we will look at here in a moment but notice here that the application is being created the app component is being used as the application and it is being mounted in the element that has an ID of app so let's take a look at this app.view and this is going to look very different than what we are used to however after I explain these things then you are going to recognize oh okay that's what it is so here we have the template if we take a look at the file that we've been working with index.html you know I've referred to the markup that was inside of our application as the template that is exactly what we have here in this new application so this template is the markup you'll see that there's this image element that's being used you'll also see that there's this hello world which is not an HTML element it is however being imported from another file that has a view extension this is another component and then there's a few other things such as an object that is being exported and then there's some CSS here don't worry about any of this we're going to go over all of these things but if we take a look at the hello world we're going to see something that looks a lot more familiar so if we look at the templates we see more HTML elements than anything else and if we scroll on down we're going to see the JavaScript for this component it has an object that has the props option and then there's of course some more CSS so this object here that we see that's been being exported that is the options object that we have been using so everything that we have talked about all of the fundamentals are still here is just in slightly different places and because they are in different places it makes it a whole lot easier to develop and maintain these applications so in the next lesson we are going to start translating our existing single page application which uses just The View Library into another application that uses the tool chain and build tools when I create a new project the first thing I like to do is delete it well not necessarily delete the whole thing but just about everything inside of the source folder because I like to start from scratch that way I know that my applications have only the things that they need and plus it's good practice because programming is a skill and just like any skill it's good to practice so I'm going to delete main.js.view I'm also going to delete hello world inside of the components folder as well as the logo.png inside of Assets Now one thing about the source folder is that everything inside of it is essentially arbitrary so this components folder it really doesn't matter we can call it whatever we want we don't even have to have it if we don't want to so we can delete everything inside of the source folder the only thing that we absolutely positively need is a file called main.js because this is the entry point of our application now we can change the name of this but we also have to change the configuration of our project and there's really no reason to do that for most projects so we're just going to leave it as main.js and the first thing we are going to do is import create app from view so this is going to give us direct access to the create app function so we don't have to say view dot create app or anything like that we just call create app and this is just like like the create app method that we used before we pass in an object that contains the options for our application and then we want to mount it to whatever element I believe the one that we want has an ID of app now one thing if you'll remember from the first version of this application is we had to create an app object so that we could create our components using the component method and then we could Mount the app to an element we don't have to do that using the tool chain because as we build our components we are able to define the components that we are using there which you will see whenever we create our app component the app component for our application is essentially going to be the options object that we passed whenever we called create app but it's more than that because remember that we also have a template and the template for our application has the nav bar and the page age viewer so one thing I'm going to do is just go ahead and grab this object whenever we create this application because we will need that let's create a new file we'll call this app.view this is the convention we have a component that serves as the container for our application we typically call that app.view and we need a template which for now let's just have some simple text and then we will have our JavaScript now Visual Studio code automatically injected this in this file and I don't want that instead we want to export a default object that contains the options that our application needs which is the data where we have an object that has the active page property as well as our Pages now we're going to add some more here but let's first of all import this app component inside of app.js and we're going to run this just to see if everything is going to work right now so we want to import app from app.view and we're going to use this app which is an object because that is what we exported from this file we're exporting this object here and we're going to use that as the options object for our application so now let's go to the command line and we want to use the view command and we'll follow that up with just serve this is going to serve our application for development purposes so this is going to take our code it's going to build it into a running application that we will be able to view in the browser and it's going to watch for changes to our files and every time that we make a change to our files it's going to automatically update our application that's running in the browser and it tells us where it's running localhost 8080. so let's open that up in the browser and we will see just some simple text which is what we would expect to see because that's all that we have right now so let's go back to our application and we want to create our navbar and our page viewer components and I'm going to create these inside of the components folder once again the components folder is completely arbitrary there's nothing special about it we could rename it we can delete it and we can organize our project however we want but it does help to have some kind of organization and I'm going to call this first file navbar.view then we're going to create another file which we will call pageviewer Dot View and just like the app component we need a template we also need a script element and let's start with our page viewer because this is the more simple one and we're going to go to our older application we're going to copy the options object that we have for and we're going to paste that inside of the script or the the JavaScript now our template we can leave here if we wanted however there's really no reason to do that because we can actually Define our template inside of the template element so let's just cut that out paste that inside of template and now this is so much easier to work with although with this particular component the template was simple to begin with the navbar is the one where we had to do some escaping but before we get to the nav bar let's go to our app.view before we export our options object we want to import that page viewer component that is from our components folder the file is called pageviewer Dot View and we want to tell this app component that we want to use our page viewer and we do that using a components option this is an object that contains the components that we use inside of this component so we have page viewer we can use that in our template but of course by itself the page viewer is kind of useless we also need the nav bar so let's go ahead and go back to our index HTML let's take the entire options object that we used for the navbar component and we're going to paste that in the JavaScript so that we are exporting that object but once again we have this template that we want to cut out of this options object we will paste the template inside of the template element but we do need to make some changes for one we need to get rid of all of the escaped characters which thankfully there weren't a whole lot but we do need to be sure to delete the correct ones and then we also have it inside of the title here so we will delete those everything else should work let's delete the templates here and so then we want to import the nav bar inside of app.v so let's just copy and paste that code to where we import navbar from components navbar.view we are using nav bar inside of app.view so we need to add that to our components and then we just need to use the template from index.html so let's grab navbar and page view let's paste them inside of the template for our app and let's see if this works let's go back to the browser we'll see that our styling does not work very well so that's one thing we need let's go to index.html let's grab this link element that references the bootstrap CSS and we're going to put this inside of our index HTML now since we are using npm we can actually install bootstrap as a dependency for our project and then we can import that into our application which is something that we will look at but for right now we are just going to take this route so whenever we get back to the browser all of our styling is there so now is the Moment of Truth whenever we click on the toggle button we can see that the style for the navbar toggles if we click on one of the links for about or contact we can see that that is indeed working as it did before now also notice that the view icon for the developer tools is lit up that means that it recognizes that view is running in this application and we should have access to the developer tools so I'm going to pull those up it's not going to show by well it is going to show by default sometimes you have to click on the plus sign for more tools and then choose view but here it is and we can take a look at our application in the developer tools so you can see that we start with app that is the container for our application then we see the navbar component that's being used as well as the page viewer and whenever we select one of these I'm going to select app over on the right hand side you can see that we have our data options so we have the active page and then we see the pages array okay now if we click on one of these links let's just go to contact you're going to see that active page automatically updates so any change that we make through our application is going to automatically appear within the data and the state of our application we can also edit this value so right now the about page is active if we change this to zero and then submit that change we can see that our application updates accordingly and the reason is very simple because view is watching for changes to not just active page but also to the pages array so if there's any change to these values or objects it's going to automatically update the Dom and this gives us the ability to easily debug if we run into any issues if a component isn't necessarily rendering correctly for whatever reason data isn't properly flowing down we can use the developer tools to debug those problems makes our lives a lot easier so there we go we have recreated the application that we've been working on using the view tool chain it does require some extra code however now our application is so much easier to develop and maintain because everything is compartmentalized into its own files now that we are using the tool chain to work with and build our application we need to talk about style because the way that we work with an import style will change just a little bit at least as far as what we are used to now everything that we have talked about thus far about applying CSS classes to elements is still valid it does not change what I want to discuss first of all is how we bring in CSS from an external Source like for example in the previous lesson I added the CD in to bootstrap inside of the index.html and while we can do that really what I want to do is take that out because I want to install bootstrap in this project and then import the CSS file into the application that way so this is what it looks like right now without the CSS from bootstrap which of course that's what we would expect and then I want to go to the command line and we will install bootstrap and we are going to save this as as a dependency and the reason why we want to save this is so that whenever we need to install everything all over again all we have to do is say npm install and then everything including bootstrap is installed so we are good to go now let's go back to our code and I'm going to open up the main.js file because this is where we will import that bootstrap CSS if you've never done this before it's going to look pretty weird but what we want to do is import from node underscore module now if you're not familiar with node at all and this is your first experience with it everything about our project is installed inside of this node underscore modules as you can see there's a lot of stuff here so everything that's here is because our project needs it either because of the view CLI or because of bootstrap so we want to leave node underscore modules alone in fact we very rarely ever open it up it can be useful because there is source code in there that you can read if you ever need to figure out how something is working but for our purposes we don't want to do any of that we want to import from node modules slash bootstrap slash dist Ford distribution CSS slash bootstrap.csn whenever we save this then the build tools are going to pull that into our application and it's going to automatically inject that in the browser now there are several advantages to doing this because we have these build tools part of their job is to optimize the files that are being built so in this whole process it is going to optimize the files from bootstrap.css as well as our source files and anything else that we import that is is ran through the build tools will be optimized as well including images so sometimes we do want some images run through the build tools as opposed to putting them inside of the public folder that's for later right now we now have bootstrap what I want to do now is a break out some functionality inside of our navbar specifically I want to take this a element and I want to essentially turn it into something like this so that we have a nav bar link and we will supply it essentially two things we will have the page that we want to display or at least the link to and then we will have something called is active and the value of this is going to be based upon whether the current active page is equal to the current index now you might think that this is a waste of time why would we want to do this when we can essentially do this the same thing with just this a element that we've done before well there are many reasons and probably the most important reason is that by breaking this functionality out we now have a component that is going to be strictly for the purpose of displaying a single link it's responsible for displaying the link as well as the different states of that link if it's active or if it's not there's some benefits to having that functionality extracted inside of its own component so as you are developing your applications you might find hey I can extract this out even if it's something as simple as this there's no harm in doing it because ultimately it makes your application easier to develop and maintain so we're going to create this navbar link component we'll have the template which is essentially just going to be that a element however we get to clean it up a little bit because we no longer have this active page but we'll get to that let's add the script and we want to export a default object let's go ahead and Define the props to where we have the page and we have that is active and then we are also going to have the computed option because we're going to create a computed property called active classes because really what I want to do is apply multiple classes whenever a link is active of course the first one is going to be the active class and we can now use the is active prop to control that the second one that I want is called emphasize and this is also going to be based upon the is active prop so that we can use this active classes right here whenever we bind our CSS classes now we don't need this click event listener we can do that here I mean there is nothing that says that we can't do that here however if we add this to our navbar link component here we are going to see that it's automatically going to be applied to the a element so that whenever we click on this a element we are still going to get the same functionality this way we don't have to Define this nav link click both here and on the navbar link and this is just one of the magical things about view this click event is going to be placed upon this a element now it's not going to work as it is right now because inside of navbar we do need to import this navbar link component this is from a file inside of the same directory so we just need to say dot slash navbarlink.view and then we need to add the components option to our options object here and we will of course reference nav barley so with that done let's just go back to the browser let's do a sanity check make sure everything is working as it did before it does so that's great but now I want to add that emphasize CSS class so back inside of navbar Link I'm going to add a style element and inside of this we'll have that emphasize and we are going to set the text decoration to underline but let's do important because I think bootstrap is going to override that so let's go to the browser there we can see the underline and whenever we click on the links of course we see the underline follow the active link that is what we would expect to see now we might think that because we defined this CSS class directly here inside of this component that it is scoped to this component that is not the case if we go to page viewer which is a completely separate component there is no relationship between that and the nav bar link at least as far as components are concerned we can go to this a element and let's add the emphasize CSS class and we are going to see it underlined as well so we can Define CSS inside of our components but by default they are not scoped they are Global however we can make them scoped to the component that they are defined in by adding a scoped attribute to the style element all we have to say is style scoped and now whenever we go to the browser we're going to see that the underline is still available for the navbar links but notice that it is no longer available for our page viewer and this means that we can go inside of page viewer if we wanted to and we could Define a completely separate emphasized class but we would probably want to make this scoped as well so let's add emphasize and let's just make this color blue something that's not an underline and there we can see that our title is blue of course whenever we go and look at the other Pages the title will be blue as well so when it comes to adding CSS to our projects we have several different options we can install them as a dependency for our project and import them just like we did with bootstrap we can also Define CSS for our components we can make them Global or we can make them scoped to the component that they are defined in as software developers our whole purpose is to build applications so that users can work with their data and as web developers our situation is a little unique because we essentially have two applications we have a server application that is responsible for processing all of the data and identity stuff and then we have a client-side application that is loaded into the browser that's what the user interacts with in order to work with with their data so you can make the argument that probably the most important thing about our application is to load data so that the user can access it and work with that data now the question becomes how do we do that because it's not always just clear cut like for example if we had a button that the user could click on and that would fetch data that was the purpose of that button that's pretty clear as to when we would fetch that information from the server however what about the data that we need to initially load so that's when the user first pulls up the application their data is right there ready for them because if we look at our application we don't really have a clear-cut way as to load that information I mean yes one of the things we could do is add a method that we could call get pages so for example the pages are data that we would want to dynamically load so we could have an asynchronous method called get pages and this would be responsible for fetching that information from the server so we could go ahead and write that code to where we would fetch the pages.json and of course in a real application this would be hitting some end point on the server application what I'm going to do is take out these page objects and inside of the public folder I'm going to create a new file called pages.json and I'm going to paste in the Json structure that has the same information is just formatted in Json so this is the file that we are going to fetch we of course need to parse that into a JavaScript object so we can use the response objects Json method and then we could return the data so that inside of data we would actually call the get Pages method and it's not option but that's a very poor option so instead what we can do is take advantage of the life cycle events of a component so in the view documentation there's this life cycle diagram which may or may not be easy to read depending upon your understanding of the terminology and just your understanding of the life cycle of a view component but basically it starts at the top where the renderer encounters a component so this is the view runtime it encounters a component that it needs to load into the browser so there's this before create event that's going to occur and this is an event that we can hook into and execute code when the component instance is initialized the props are resolved but there's no processing as far as the component's data or computed properties so in the terms of our needs the before create isn't really some something that we would want to use to load data primarily because we want the data to already be processed as well as the computed values as well so let's go back to the diagram after before create then there's the initialization of the options API that is the API that we are using up here at the top you can see that there's this setup and then this composition API the composition API is a different way of creating the same components that we are working with and we will look at the composition API for now we are working with the options API so after the options API is initialized then there's this created event this created event occurs after the data and the computed properties have been processed but before the component is loaded into the document in the browser so this is ideally the place where we would want to load our content because this means that the data is processed so that whenever we load our data data then view is going to be able to react to that change but it's before it is visible in the browser which is very useful for the end user experience so we want to use this created event and all we have to do is add created as a method to our options object so this is just another option just like if we wanted to use before create we would do the same thing and then inside of this created method we would call our get Pages now we could assign this to the pages in our data like that or what I would probably do is something like this so that's inside of get Pages we would go ahead and set Pages equal to our data so with that simple change we can go to the browser and we are going to see something that looks a little weird we have two navbars so let's look at the developer console because we are going to run into an error here it says that it cannot read properties of undefined it's trying to read page title and it tells us where that is pageviewer Dot View so let's open up page viewer and let's see it is right here on line three it's trying to access this page title property but it does doesn't exist and the only reason why that wouldn't exist is because this page object is null or undefined and the only reason why that would be null or undefined is because the page that was passed as the page prop is null or undefined so basically it's this Pages before our data has been loaded pages is an empty array so undefined is being bound to the page prop for the page viewer and we're running into that error so then the question becomes how do we address this and there are a variety of different ways which is what we are going to look at in the next lesson in the previous lesson we loaded data into our application by making an HTTP request from inside of the created hook so we retrieved that information we parsed it into a JavaScript array and then we stored that array in the pages data property however whenever we view this in the browser it still kind of works but it looks really weird because we have two nav bars and if we look at the console we have an error and it's because of this right here the page viewer component is getting the value of undefined past for the page prop and the actual error is that it's trying to use the page title property on undefined well of course undefined doesn't have any proper so that is of course going to fail and the reason why we are seeing this is because pages is initialized as an empty array and it's not populated until the component is initialized the data is processed test and then the created hook executes so there's this tiny little brief moment where pages is empty and the page viewer is trying to retrieve the element at index 0 from an empty array which of course that's impossible so undefined is passed to the page viewer so there's a couple of different ways that we can get around this particular error and probably the most straightforward is to do something like we would do in just normal JavaScript and that is to check if we have any elements inside of the pages array we can do that using a directive called the if this is very much like the if statement in JavaScript and we can use it on any element it doesn't have to be an HTML element or a component as long as we use it and we provide a truthy or falsy value it's going to work just fine so here we want to check if the length of pages is greater than zero and this is going to do one of two things if the value of the if directive is true then page viewer is going to be output into the document if it is false then it is not going to be in the document at all so let's take a look at this let's refresh just to load everything from scratch notice that we now don't have two nav bars and we don't have any errors inside of the console and everything works like it should if we take a look at the elements we can see of course we have our nav bar we also have the div element that contains the Page information but let's do this let's set the value of false for the page viewer let's go back to the browser and let's refresh the page we are still going to see our nav bar because what we just did does not affect the navbar at all however we don't see the page content and if we look in the elements we see this V if HTML comments where that div element would be so that div element is not in the document at all it is completely gone and it will stay gone until the value of that V if directive is true so this approach is very much like what we would do in just typical JavaScript if the length of pages is greater than zero then display the page if it's not then hide it now there's a similar directive called the show and its purpose is to show or hide content but it does so in a different way instead it uses CSS to show and hide the element so if we use V show here we are still going to run into an issue because from the standpoint of the page viewer it is still in the document even though it would be hidden with CSS whereas with v if it wouldn't be there at all to generate an error so let's take a look at what V show would do so let's create a div element we don't need any classes or anything like that let's just have V show and let's set this to false so that we will hide this content so of course we're not going to see this rendered within the browser however whenever we look at the elements we will still see that element is there it's just that its display has been set to none so you can show and hide content with two directives V show uses CSS to hide the content the V if directive does not output that element at all if it is false so that is the first way that we can solve this particular problem the second way would be to provide a default value for the page prop and we would do that inside of the page viewer component now this approach can be a little tedious because it changes the way that we Define the props for our component instead of using an array of just simple string values we would use an object where the property names are the names of our props and then there would be a descriptor object that would be used to validate that prop as well as provide default values so the first descriptor would be the type so this is an object if it was just a simple string we can use string or number or whatever but this is an object and since this is an object we can provide a default value but we have to write it as a factory function if this was a simple value like a string then all we would need to do is provide the string value but since this is an object we have to write this as a function to where we receive the raw props but in this particular case we don't really need any of that information we just need to return an object that has a page title property we can initialize that as an empty string and then we can also provide the content which would be an empty string as well so you can imagine if you have a component that has a lot of different props if you decide to use an object to Define your props you're going to have to essentially describe them so at the very least you would have to have an object for each prop and have the type for each of those props but this is going to fix our problem as well because we have now provided a default value for our page so if undefined is passed this default value will be supplied to where page title will be an empty string so let's refresh to start from scratch and once again we see the behavior that we would expect and the application works just fine now there's no right or wrong approach to this but they do serve different purposes if you choose to define the descriptors for your props this is primarily for prop validation just so that you would get better error reporting as you're developing your application whereas using the V if directive would be the more straightforward and simple approach I either way it gets the job done when you start incorporating data in your applications especially loading data it can be confusing as to when you should load data and unfortunately there are no hard and fast rules that say that you should load this data when it is completely subjective it depends upon your application it also depends upon your opinion of when your application needs to load that data but what I typically do is boil it down to two criteria is the data used across multiple components or is the data specific to a single component so let's look at an example of both of those now we have the pages array inside of the app component and of course this is the pages that our application is using to generate the links in the nav bar the pages array is also used to display the content of the current page so while the page viewer doesn't necessarily use the pages array inside of the component it is dependent upon the pages array so since this data is used across multiple components I want to load this as soon as possible or at least before those components are created and loaded so in our case it made sense to load the pages inside of the app component using the created hook so that's great but let's take a look at the nav bar because the nav bar has data now of course it has data being supplied through the props such as pages but there is data that is specific to this component and only this component and it's this the theme now in the grand scheme of things this data isn't as important as the pages because without the pages the application doesn't work at all but this is part of providing the user's experience we give them the ability to change the the theme of the nav bar so it kind of makes sense to go ahead and store that information so that whenever they revisit our application we can load the settings that they prefer now you could make the argument that settings are also an application Level component because when you start talking about settings there are components that would have different settings and it can make sense to load all of that information up front however you can also make the argument that it should be loaded by whatever component is going to be using that setting and that's what we're going to look at in this lesson so when it comes to storing and retrieving the theme information we can approach this in a variety of different ways and there's no right or wrong way I'm going to take the most straightforward way in this lesson and later on we will probably readjust it so that you can get an idea of another way that we can approach it so for this lesson we're just going to add to method it's one that is going to store the theme setting in which case what we'll do is take whatever is inside of the theme data property and store it in local storage now we need to decide upon what key we are going to use and I think theme is going to be just fine so that we will set an item in local storage the key is theme and the data will be whatever is inside of the theme data property let's copy this because this is going to be the basis for get theme setting in which case we want to retrieve the theme in local storage so we will call the get item method with the theme key now it is possible that this item doesn't exist in local storage the first time the application is loaded into the browser it definitely won't be there so we do need to check if we have a value if we do then we can go ahead and we can set the theme equal to whatever is in the local storage otherwise we'll just leave theme as the default which is light and so then we just need to decide when we use these methods so we need to store the theme setting whenever we change the theme so that makes sense to call it after we set the theme and then we can call the a get theme setting inside of the created hook so let's go ahead and let's create that method we will call the get theme setting and that should be fine so let's go to the browser let's pull up the developer tools so that we can go to the application tab so if we go to local storage and then the URL here we can see that there is not a theme key whenever we click on toggle and then we refresh local storage we see that the theme is set to dark so if we refresh refresh this page then the theme should probably be set it is if we change it back to the light theme let's refresh our local storage we see that it is now light we refresh the page and of course that setting is loaded now as I said this is completely and totally dependent upon your application it's also dependent upon your opinion of when you should load the data within your application as we add more settings it might make more sense to load everything up front so that's we aren't hitting local storage multiple times all at the same time but then again it is application dependent and also don't be afraid to make changes to your application sometimes designs change we very rarely never get it right the first time so go with what makes sense if that changes later on well that's why we are Developers we can't talk about data without talking about getting data from the user and the primary way that we do that is with forms now traditionally forms are the most tedious thing that we can work with in JavaScript but thankfully view makes it so much easier in fact it is dead simple so what I want to do in this lesson is essentially take out the page viewer because we know that that works and eventually we will add that back but right now I want to focus on forms and I want to create a new page object that we will eventually add to our Pages array and we're going to do this inside of another component so let's just call this create page and this component needs to have a callback so that the app will know when a page has been created so let's just call that page created and we'll handle it with a method called page created let's define that inside of our methods here inside of app and for right now let's just take the page object that this is going to receive and write it out to the console and eventually we will then add this to the pages array so that's the basic functionality here inside of the app component we can go to our components folder and let's create a new file we'll call it create page Dot View and as far as the template is concerned I already have the markup just because it's a lot of typing and there's really not a whole lot here there's two form Fields one for the page title one for the content and then there's a button which is going to execute that page created so we know that we have that prop let's go ahead and Define that and we can use just the simple prop definition there's no need for us to use the descriptor object notation and we know that this page created is going to execute whenever the user clicks on the button so let's go ahead and set up that click event and we don't necessarily know what we are going to pass we well we know we're going to pass an object we don't know what the values are going to be yet so we have all the Preparatory stuff ready to go now we can focus on getting data from the form now with traditional JavaScript we would typically apply an ID to the input and the text area elements so that we can reference those elements get their values and then we're good to go we can't necessarily do that with view because remember that we are inside of a component which means that if we wanted to we could use multiple create page components within the same view component which then we would have multiple text area multiple input elements that have the same IDs which that's not going to help anyone so instead we need to think about using tools that we already know about such as binding data so for example for our page title we could do something like this to where we bind to the value of the input element and we could call this simply page title which means that we would need to Define this inside of our data so let's go ahead and do that we can initialize it with an empty string and that's great so whenever we click on page created we could include the page title there so let's go to the browser and we don't see our form because I did not import that inside of the app component so we want to import create page and we want to include that within the components option so there we go now we should see the form let's pull up the console so that we can see what result we get whenever we click on create page let's just click on it we see that we have an object with page title that is set to an empty string which makes perfect sense that's what we would expect because we haven't provided a title yet but let's provide a title let's click on create page and notice that the output is the same page title is still an empty string and the reason is very simple because whenever you bind data using V bind yes you are binding data but we are essentially saying that the value of this input element whatever page title currently is which right now it's currently an empty string so if we provide any text as the initial value for page title whenever we go back to the browser let's refresh we're going to see that value being displayed for page title it's a one-way binding so instead what we have to do is update page title whenever the value of the input element changes and we can do that with the input event this is the normal Dom input event so we can have a function that's going to handle the input event we get the event object and we will set page title equal to the Target of the event which is this input element and we would get its value so now we have this two-way binding so now even though we have a one-way binding with the value and the page title now we are updating the page title whenever the value in the browser changes so let's go back to the browser let's type in something let's click create page and now we see that the value is what we would expect it to be page title is a title but also remember that I said that view has the easiest way of working with forms this necessarily isn't very easy however there is a directive that we can do that essentially does this same thing and it's called V model and this sets up a two-way binding between this input element and then whatever we specify as the V model which is going to be page title so now we're going to see that same functionality we can see that the page title is initialized with that initial value let's change that because that's that's silly so we'll initialize it with an empty string so that it is empty but then no matter what we type inside of this we will see it as the page title so let's click on create page and there we go so in order to work with simple form elements all we need to do is use this V model to bind a data property to that form control and that's it so we can essentially do the same thing for our text area so we will have a data property called content we will use V model to bind that content to this text area so that then whenever we click on our create page button we will provide both the page title and the content so let's go back to the browser although we do need to initialize content with the value so let's go back to the browser and let's refresh the page because we did have an error there and now let's provide a title let's just call this page four title and this is the content whenever we click on create page we will see in the console that we have an object that has the content that we typed as well as the page title in the previous lesson I introduced you to the V model directive so that you can set up a two-way binding between a forum control and a data property and that's all well and good but there's more to working with forms than just getting information we also need to be able to validate the information and it would also be useful to have some visual cues for example if the form is not valid then we could disable the create page button and it could stay to disabled until we have a valid form so let's start by changing up a form because the object that we are creating is not complete we also need a link so we need at least two other pieces of information such as the text and the URL for the link so I'm going to paste in some new markup it's just changing our form so that now we include the link text and the link URL I also have this published checkbox which we don't have to worry about just yet but the idea is going to be that if it is published then we see the link in the menu bar if it's not then we don't so the first thing we need to do is set up the two-way binding between the form control and our data properties for the linked text and the link URL and of course we don't have those values but they're going to be simple enough to create we'll call the link text just link text for the URL we'll call it link URL and we will initialize these values as empty strings as well now because we are adding this extra information it makes sense that we modified the code that is handling the click on our button because we just called page created we passed in a simple object with a page title and content now we need to do some validation and we need to build a more complex object so let's define a method we'll call it submit form and we need to add that to the methods option now as far as this submit form method is concerned we don't need any external data such as the event object which would be passed here and the reason is because all of the data that we need is right here inside of our data so the first thing we're going to do is going to be rather tedious we need to make sure that we have some values in fact we need all of the values because in order to create a page object we need a title we need the content and we need the link information so if any one of these values is missing then we can't do our job and create that object so we are going to alert to the user that they need to fill out the form and then all we need to do is return because there's nothing else for us to do but if we do have all of the data then we can call the page created function and then we will pass in an object that has the page title the content and then we will build the link object which has text and URL properties so with that done let's do a sanity check let's see if everything is going to work so let's first of all click on the submit button and we see that of course this is not going to work please fill out the form so let's just add some content and make sure that we aren't going to be able to submit this object without providing all of the information and we should still have everything set up so that we output that object to the console and we do so there's the content the link and the page title that's fantastic now I want to set up a visual cue so that the button will be disabled until the form is valid and that might seem kind of redundant especially since we've already set up the submit form method to check these values but it never hurts to have redundancy especially when it comes to checking if something is valid or not and besides having a visual cue is always a good thing so we can accomplish this in a couple of different ways but probably the easiest and most straightforward will be to use a computed value and let's call this is form invalid which kind of sounds weird because I would typically want to say is form valid but we're going to be binding this to the disabled attribute on the button which means that when disabled is true then of course the button is disabled if it's false then it's not so the wording is to make it a little bit easier to understand what's going on so that we don't have to parse it out and do something like this is not is form valid so it's just to make things a little bitty so if is form invalid is true that will disable the button so now we just need the code to check if the form is invalid and we basically already have that if any one of our values is empty then that will return true so we can go back to the browser and we can see that the button is disabled and as we start adding values see it is still disabled until the entire form is filled out if we clear out any one of the form Fields it goes back to being disabled and of course whenever we submit the form the object is sent back to the parent that app component where we can output that information in the next lesson we are going to modify the pages array so that whenever we create a page it will update the menu but we also want to only display the pages that are published which means we will need to filter the pages that are in the nav bar in this lesson we are essentially going to do two things we will first of all add the code to add page objects to the pages array so that we will display those in the nav bar but we also want to take into account this new published value so that if a page is marked as published it is displayed in the navbar if not then well it's not so let's start with the easiest thing and that is to modify the pages array in this really literally cannot be simpler all we need to do is push in the new page object and we're done so the lesson here is that anything that modifies or mutates our Pages array is going to automatically signify to view that this data changed update all of the UI that uses the pages array so any built-in array method that mutates the array and there are several push pop shift unshift splice sorts even reverse those are methods that mutate the array so therefore those changes will be reflected in the UI so with that simple change we can add a new page we can say that this is Page four and we'll just have some content we're not really displaying this information right now for the linked text let's use page four as well and in fact we might could do something to make this a little bit easier from a data entry standpoint because a a lot of times the page title might be the same for the page link so that's something that we might want to consider and then for the URL let's just call this page4.html and we will click on create page we see page 4 in the menu bar and the URL is page4.html so as far as that code is concerned we are golden now we just need to take into account this published value now this is going to require us to modify our pages.json file because this is the original place our data is coming from so let's do this for the home page we'll set published to True we'll also do the same thing for about but for contact let's set it to false so that we will not see that in the navbar so with that done we need to go to our create page component because we need to take that published value into account so we need to set up a v model for that check box let let's just call it published and let's initialize this as false so that if something is supposed to be published we have to check it although it might be something that we want to default it as true I guess we can default it as true it really doesn't matter and we can see inside of the browser that yes it defaults to true so we're good there but we do need to take that into account whenever we call page created so we'll add the published property there and we should be good to go except we need to filter what we have in the nav bar and the most straightforward way to do that is with a computed value so let's go to navbar we'll add the computed option and let's just call this published pages and we don't want to modify the pages array in any way instead what we need is to return an array that only has the published pages and we can do that with calling the filter method this accepts a callback function that returns a Boolean value if it's true then that element in the array is going to be in the new array if it's false then it's going to be left out so in our case all we really need to do is check for published and that will give us the filtered array so now we can use published arrays in our for Loop so we will replace pages with published Pages let's go back and voila we see home and about so let's add another page with some content the link text Will mirror whatever the page title is URL really doesn't matter because we don't have that to begin with whenever we click on create page we will see it and whenever we create a page it would be useful to clear that form so let's add that code as well so that after we call page created we set all of our properties back to their original value and this can be a little tedious process and if this is something that we need to do multiple times then we can just write a method called clear form and that would reset the form to their original value so just to make sure everything works as we expect it to let's add yet another page that has some content the linked text will be yet page URL will be yet.html ml but this will not be published so before we click on create page what I want to do is go to the view developer tools because I want to see what the app data is going to be so here we have the pages array we can see that we have four pages but we are of course only displaying three because the contact is currently set as not published so we are going to add another object here that is not published so we don't see that in the nav bar but we didn't see the pages update did we let's go back let's go to another component let's go back to app end there we go now we have five elements in the array and the really cool thing about this is if we change any one of these published values we're going to see the results automatically in the browser so let's change published to true for contact and there we can see that well in the next lesson I think I want to make this a little bit easier for the end user because there is a relationship between the page title and the link text a lot of times they are going to be the same so it would be nice that as we type into the page title that we see the linked text automatically update but of course it's not going to be as simple as that because nothing ever is but it'll be a nice feature nonetheless in this lesson we are going to enhance the user's experience as they create a page and the reason is because there's almost a one-to-one relationship between the page title and the link text for the majority of pages they are going to be the same so I want to do this as the user types into the page title I want those characters to be automatically replicated in the link text field so that for the vast majority of pages the user doesn't have to type that value that would be a huge production boost and as a software developer it is is my job to empower the user to get the work done that they need to get done however it can't be that simple because not every linked text is going to be the same as its page title so in the case of when the linked text is different we need to be able to preserve that value so that when the user updates the page title that isn't reflected in the linked text so this sounds rather complicated but in actuality it's very simple to implement we are going to use what's called a watcher to add a watcher we need to add the watch option to our component and then we create a method that has the name of the value that we want to watch so in our case we want to watch the page title because that is what the user is going to be typing so in the value of page title changes this Watcher is going to execute and it's going to give us access to the new title value as well as the old title value and this is really all that we need to do we need to check what the link text is we need to see if it is equal to the old title because if it is then we know that the user hasn't changed the link text so in this case we would then update the linked text to the new title however if the user changed the link text then of course it's going to be different from the old title in which case we don't do anything at all so we can go back to the browser and we can test this out so as we start typing into page title we can see that the linked text is automatically updated this is going to save us a whole lot of time so that we can add some content then we can add the URL and then we will be done so then we can start adding the fifth page but the user might decide okay I want a different value for page five really releases for the link text so this is going to be some page but then yeah I don't want the page title to be page five this will be uh something completely different and notice that the linked text is staying the same value so we have the functionality that we want and we could even take this a step further by doing something with the link URL there are so many different ways that we could approach that we could take the linked text we can make it a lowercase replace the spaces with an underscore and then automatically populate the URL I mean there's a lot of things that we could do to make the end users lives a little bit easier but instead of doing that I want to talk about the differences between a computed property and a watcher because there is a lot of confusion between the two but basically it runs down to this computed properties simply return a value they use the existing data in order to compute a value that is then used in our template it does not make any change to our state it does not mutate anything at all it simply computes a value based upon the current data The Watcher on the other hand watches for a property to change and it gives us the ability to make changes to our state so computed values compute and return a value Watchers watch for a value to change and allows us to mutate our state remember those two rules and you will have no problem using computed properties and Watchers correctly events are the lifeblood of any application with a graphical interface it's the primary way that we interact with users but in the terms of our View application it's also a way that components can communicate with one another now technically the only events that we have used thus far are Dom events anytime that we have set up the click event for a button and even the click event that we set up inside of the nav bar you know we have this navbar link component where we set up the click event even though that's done on the navbar link that's actually following through to the a element that is directly inside of that component so everything so far has just been a typical Dom events now we have emulated events like for example inside of the create page components we have that prop called page created to where we bound a function to that prop so that whenever the page object is created we call that function and then we've emulated that event but that is technically not an event we can however create our own custom events and there are benefits to doing so as opposed to emulating them like we have done like for example we can actually simplify our component because we don't have to declare player our events we can if we want to and there might be some benefits to doing that but we don't have to declare them so that's one thing the second thing is that it makes our code easier to read Because let's look at our app components so we have our nav bar where we've bound a lot of data to different props then we look at the create page component and we have bound something to page created but we don't necessarily know what that is until we look down at the code and we see oh this is a method so this would be a lot easier to read and understand what exactly is going on if we were using the actual syntax for setting up an event handler so now we have a page created event that we are handling with a function called page created we don't have to dive into the code within our component in order to figure that out because it's very clear as what we are doing with just this line in our template so now we just need to make this work with a custom event and it's very easy to do because all we need to do is emit that event we have a special property called dollar sign emit now the dollar sign is there just to say that this is a public property so this is something that is legal and actually encouraged for us to use inside of our components it's not something that's private or hidden so we want to emit an event called simply page created so for the first argument we passed the name of the event that we want to Emit and that will emit that event now there's something to notice here I'm using camel case for the name whenever we emit this event whenever I set up the listener I use a dash in between the page and created so I'm following the same rules that we have for props except that this is of course for events so if all we needed to do is emit the page created event then we're done but that's not it we also need to supply the information involved with that event so for the second argument we're going to pass in the object that is created when this page is created so let's save this let's go to the browser and let's test this out everything else should work just as it did before so all we need is some data inside of these fields so that we can click on create page and there it is there's the page that we just created and because we see this here that means that the page created event occurred and the app component handled that event just fine now I said that we don't have to declare our events inside of our components but we can if we want to and there are benefits to doing so so first of all the easiest way to declare an event is to use the emits option and this is a lot like the props to where we can supply an array that contains the names of the events that that we emit from this component so page created and that would be the easiest thing that we can do we can also set up the emits property as an object so that we can perform validation for our events so for example the page created event needs to supply the page object that was created so inside of this method we can write the code that will validate the payload that we are sending through the page created even so for example if we check if the page title is not there then we would want to return false because the validation of that object failed it should have a page title and if we needed to supply any information we could do that by just writing something out to the console or we can look at the console in the browser so let's just return false let's say that regardless of what we pass for the page created event it's not going to pass validation now this isn't going to prevent our code from executing as you'll see let's refresh so that we start out with a clean nav bar let's add a new item let's pull up the developer tools so that we can view the console we'll click on create page now we'll see this warning in the console invalid event arguments and that the validation failed because we returned false in our validation code for the page created event however look at the navbar there is the object that we just created so it's not going to prevent our code from working but it does give us the ability to validate those objects that we include with an event so let's do that very quickly let's break this page object into the different pieces so that we have the page title we have the content and then we have the link and we also have published don't we so we have four pieces of information so now we can check if we don't have a page title then we will return false if we don't have content then we will return fall then we can check the link if not link or if not link and what was it text or not link and URL then of course we will return false and then we can check the type of our published so if type of published is not Boolean nah let's not do that let's just leave published alone so if everything else passes then we will just simply return true and there we go once again this is 100 optional you don't have to declare your events you don't have to validate them but the ability to do so is there and it can definitely make it easier as you develop your applications and as you you are debugging them the ability to create custom events is a fantastic feature and it's one that you will use in the majority of your applications but there are some limitations and probably the most cumbersome is that component emitted events do not bubble well what do I mean by that well let's just think about normal HTML and JavaScript let's forget about view for a minute and let's say that we click on a button well that is going to generate the click event and the target of that event will be that button element but the event doesn't stop there at least by default it's going to Bubble Up to its parent which is the form element then from there it's going to Bubble Up to its parent which is the div element that will then bubble up to nav and it will keep bubbling up till it reaches the top of the element hierarchy and the fact that events bubble gives us the ability to trigger an event on an element and then we can listen for that event higher up in the hierarchy that might sound like it's not very useful but I guarantee you it is so now let's think about a view component whenever you emit an event from inside of a component that event can only be listened for inside of the direct parent it does not Bubble Up the component hierarchy so for example we set up a custom event inside of the create page component where we emitted the page created event we listened for that event inside of app now of course app is the top of the hierarchy but if there was anything higher than the app that event would not Bubble Up it stops here inside of the app component and that can be very cumbersome because there are times that we need to listen for an event that occurs deep within the component hierarchy and there are ways that we can get around that like for example I'm going to refactor our navbar link here so that's inside of the navbar link we have the l i element so we're going to generate that here inside of navbar Link instead of inside of navbar I think that it makes more sense in that case that means that we need to take the for Loop and all of the other stuff and place that on navbar link we can get rid of this Li element and for the most part that's going to work just fine however now I'm going to say that it really doesn't make sense to listen for any kind of events here on the navbar link instead we would want to emit an event from inside a navbar link so that whenever we click on a link we will set up the event listener to emit an event which we can call Simply activated but in this particular case case the only component that needs to know that this link is activated is actually our app component because that is where we actually do something so in order for the app component to know that the activated event occurred we would have to chain events so that inside of the nav bar we would listen for that activated event but then we would emit something else it could be called activated or it could be called something else and then we'd have to pass on that information so that then we could listen for it inside of app it works but it's very tedious and it makes our code much more complex it also makes it much more difficult to understand at a glance because we have to follow the chain of events so in Prior versions of view what we would do is create what's called a global event bus it allows us to essentially emit e events globally so that we can emit them from any component and listen for those events inside of any other component regardless of the relationship between those components the problem now is that with view 3 we don't really have that ability we have to write a lot of extra code in order to make our own Global event bus and it's frustrating to me at least because this was a pattern that was very commonly used in view version two and I would have liked to have seen something like this built in but with just a little bit of extra code we can write our own Global event bus so here's what we are going to do inside of the source folder we are going to create a new folder I'm going to call it utils the idea being that this is going to contain some utilities that we can use within our application and one of those utilities is going to be called events so we'll just call it events.js and we're are going to create an object actually we're going to create a map that we will use to keep track of all of our events and then we are going to export an object that will have methods that allow us to set up events as well as emit them so let's start with the method that will allow us to listen for events I'm going to call it on very similar to the idea from jQuery to where we could use the on method and then we can specify the event name and then Supply the function although in this case let's just call this Dollar on because that follows the convention that we would find inside of our view components so here we want to check to see if we don't have an event with the given name and the map object gives us this has method so that we can check if we have a key with the given event name and if we don't then we will create one and we'll give it a value of an empty array so that then we have an array and that's how we are going to keep track of all of the functions that are set up for a given event so we will get the array for the given event and then we would push in the function that we wanted to listen for we could do something similar to remove an event but this takes a little bit of extra code so I'm not going to actually implement this we will have this method so that if we do end up needing it then we can implement it later so for now I'm just going to throw an object that has a message that says not implemented and that's going to be fine and then we need a method to emit our event to trigger it if you will I'm just going to use the same terminology that's used inside of view and that is to emit an event so we need the event name we also need any provided data and once again we need to check if we have have any events with the given event name and if we do then we want to execute all of the functions that have been set up for that event which is very easy to do we once again want to get that array and we will simply use the for each method to where we will execute the function passing in the data and there we go so then the question becomes how do we add this object to our application we want to make it very easy to use so one thing we can do is just add it to all of the components where we want to use it and import it and all of that stuff and no that's a lot of work instead what we will do is make it part of our application so that we can use it from inside of our components wherever we want and we don't have to import it anywhere else except from inside of main.js so let's import this object I'm just going to call it dollar bus and that is from utils events and we need to break up our line of code where we create the app and then we mount it kind of like what we did way back whenever we started this journey so that in between creating the app and then mounting it we want to add to our configuration there's a property called Global properties and this allows us to add properties to every component within our application so we can call this dollar bus we can call it dollar event bus we can call it whatever we want it doesn't matter but I'm going to call it just simply dollar bus and we will assign it that value so now every one of our components is going to have this dollar bus property so we can use our Global event bus from anywhere so that means inside of navbar Link what we can do is use our bus we will call the emit method and we need something a little little bit more descriptive because now we are dealing with global events so let's call this navbar link activated and it would be useful to provide the index which we don't have but that's easy enough to do we can add index as a prop and then inside of navbar we can add the index here and I guess we should probably rename this from navbar link to navbar item but we'll leave it like it is for now so now we just need to listen for that event and we can do that inside of app but before we do did we have any other code here we had this nav link click prop we can get rid of that and I don't think we reference that anywhere else so we should be good to go so that's inside of app all we need to do is listen for that event so that's what we would do is set our active page equal to the provided index so let's cut that out let's get rid of this nav link click prop and since we already have this created hook here this would be a perfect place to listen for that Global event so we're going to use our bus object and we're going to listen for the navbar link activated and this is going to give us the index so that then we can set the active page value equal to whatever the index is so this should still work as I should because I haven't actually tested this with a map I've always used just atypical object instead of a map but to me a map fits this purpose better than a normal object so let's go to the browser let's refresh here and let's click on our link and nothing is happening so let's take a look at the console we have some errors here so events names is not defined and that's because I mistyped it somewhere inside of events so that would be here line 18 so let's get rid of that s let's go back to the browser and let's try this again let's click on about and it looks like it activated if we click on home we see the same thing so that looks like it's working let's go to the app component and let's uncomment out our page viewer just so that we can see if the page is going to change as well so let's refresh we have our content if we click on about we can see that that's changed as well so we are good to go we now have a global event bus that we can use in our application now a lot of times you might not need a global event bus but if you do that's how you can Implement one our little application is technically a single page application it is a single page that is loaded into the browser and then we are able to navigate to other pieces within the application like for example for now all we can navigate is between the home and about pages but if you think about it this isn't very scalable because the pages that we currently have are all of the same kind in fact it's data driven it's driven by the data for those pages but we also have the page created component that has a form so that we can create more pages that would ideally be inside of another page that we would navigate to and then if we had any other utilities such as being able to list all of the pages and edit them all of those would be in other Pages as well so if you plan to do any kind of navigation within your applications it makes a lot of sense to just go ahead and get started with a router now let's install the router and then we will talk about what it is so for our view applications we want to install the view router and we want to save that to our project now a router in the sense of software development takes user input and routes it to some piece of code that is going to handle that input if you think of a server-side application like laravel or asp.net there is typically a routing engine that is looking for incoming requests and it will route those requests to different methods on a controller well the same idea applies to our View application we have a router that is going to Route URLs to a component so that it essentially treats an individual component as a different page within our application but the entire application is loaded within a single page now the reason why you would want to start with a view router to begin with if you have any kind of navigation is because it changes the way that you need to develop your application like for example we have this app on it which is essentially the entry point of our application I know that the main JS file is but this is where we load our data this is where we pass data on to the other components so this is the main piece of our application but whenever we introduce the ability to navigate to other Pages well the way that we interact with our data changes because it's not necessarily something that we can just load here inside of our app component instead it's something that we almost have to do inside of each individual component that is going to be working with that data and you'll see why that is so the first thing we need to do is Define the routes for our router and we're going to do that inside of a separate file and we can just call this routes.js and the first thing we need to do is import two functions the first is going to be called create router this is of course what we use to create the router but whenever we create the router we also have to tell it how to handle the URLs or at least how to handle the history and since we don't have any backing server-side application what we are going to do is use the web hash history so we need to also import this function called create web hash history and we're going to use that whenever we create our router so we want to import these from view router and then we will create our router we will call the create router function and then we will pass in an object the first property that we need to Define is the history how is the history going to be treated within this router and this is where we use that create web hash history and then the second property are the routes that we are going to Define for our application this is an array of objects and the most simple objects are going to have two things it's going to have the URL path this is essentially what we would see in the location bar and this is how we determine what requests get routed to which components so the home of our application would be just a slash and then we would need to specify the component that is essentially going to handle that URL so in the sense of our application whenever we navigate to the home whatever component we specify is going to be displayed now we have something already available that is responsible for displaying content and that is our page viewer however if you'll remember the page viewer is very dependent upon the data that it receives it needs to be able to display the individual pages and we would pass that data through props well now that we are going to use a router we can't really use props I mean we can but all the data that's going to be passed to the component is now going to be done through the URL as opposed to a parent component so we are essentially going to be breaking our application and then we will fix it so that it will work with the router so we have our home route which is going to be our page viewer but then we also need a route for being able to create a page so let's define a route that has a URL of Slash create and then we want the create page component to be displayed whenever that route is handled now of course we need to import these components so let's first of all import the page viewer from our components folder page viewer then we also need the create page component as well and then after we create this router we are simply going to export it so that we can then import that inside of our main file now we still get to say that our app component is going to be the well the app component but then we will tell tell our application that we have this router that we want to use let's import that from routes and then we want to call a method on our app simply called use the use method lets us pass a plug-in and the router object that we just created is a plug-in so that we tell our application to use the router we still need to modify our Global properties and then we Mount our application now the other change that we need to make is inside of our app component we still want our navbar here but everything else we don't want because the router is going to be loading this information and we tell our application that we want to display that router information right here with this router view component so the component that's going to be loaded by the router is going to appear here or if we wanted it above the nav bar which doesn't make a whole lot of sense we could do that as well but the idea is that this is a placeholder so that whenever the view router navigates the user to a component that component is going to be displayed right here so our page viewer is not going to do anything right now so let's change this so that we have some text that we can see so we'll just have the page title and then we will have the content and whenever we go to the browser we should see that we have our navbar and then we have the page title so notice the URL we have a hash that's because whenever we created the router we told it to use the hash history so if we want to navigate to the create page we will need to say hash slash and then create and that will take us to the create page which you can see now is our create page component and so now the question becomes how do we get our data now of course the navbar is still displaying the links to those pages and the reason is very simple because we are still loading that data inside of the app component and we're passing those pages onto the nav bar but we've now just effectively broken the functionality of this active page data because that's what we used in order to display the given page now of course the active page was dependent upon knowing the index of the page that was currently displayed that information is now in the URL and we can get that information from Route params which we will look at in the next lesson before we just dive in and start refactoring our application we first of all need to talk about how we need to refactor our application and let's first of all just briefly recap of what we had so we had an application that relied upon an array of page objects and we used this array in order to build a menu this menu had some links that whenever we clicked on the link it didn't really navigate us to a different page but it did load the content of the page object that was associated with the link that we clicked on and all of that was handled through the app component it kept track of whatever link We clicked on and then it provided the page to the page viewer component so that then the content would be displayed but in the previous lesson we added the view router and that drastically changes the way that we are going to use our page viewer component because now page viewer is handling a route right now that route has a path of just a slash which is the root of our application and unlike before we can't just pass the page to display as a prop instead we need to start thinking in terms of just typical web applications so if we forget about view for Just a brief moment let's imagine that we have a blog websites and we want to display an individual blog post well the way that we would do that is to have some kind of unique identifier in the URL that way the blog application could pick out that data from the URL it could fetch the information from the database and then display that in the web page that's basically what we need to do with our application we need to provide the unique identifier for the page object that we want to display so that we can fetch that object and then display that inside of page viewer so all of the data that page viewer is going to rely upon is going to come from the URL so we need to denote inside of our route that there is some unique identifier that we need to work with and we do that with what's called a param a param starts with a colon and then it's followed by some name and in this case I'm going to call it index because that is how we have been referring to individual page objects so this route now has a path that expects an index something that we can use to then go and fetch our data and display that however this is going to have a side effect that I'm not all that wild about because now as you look into the console it says that there is no match found for the location with a path of just a slash so I want this application to work like this if we don't Supply an index then it's going to provide the default page that could be index 0 or that could be the lowest index of a page that is published but if we do Supply an index like an index of one then we would display the page with that index of one at least as long as it is published so this means that our index param needs to be optional and we can do that very easily by just adding a question mark at the end of the param so this is going to fix that particular problem so that now index is optional it is actually an empty string whenever we go to retrieve that so now the question is how do we retrieve that value of that index param well let's go to our page viewer because this is now the component that is handling that route we don't have the page prop anymore so let's go ahead and just get rid of our props all together and let's add the created hook so in the previous lesson whenever we created our router we added it to our app with the use method this was for including a plug-in with our application and whenever you do that we get a special property that we have access to in all of our components called simply route this refers to the route that is currently being handled by this page viewer component so this has a property called params which is an object that contains all of the params that would be defined inside of our route path so we only have one and that is index so we can actually write this out to the console so that we can see what that value is and if we just write out the params then that's going to show us the object and everything inside of it so whenever we go to the browser we can see that we have an index but it is an empty string and of course we could add some other value for the index let's add index one and we can see that's the value of index is one now there's a caveat with this and that is it doesn't matter what we include as the index param it can be a string of characters and index will be that value so there is some validation that we will need to do so let's do this for the content let's take the index param and let's just display that as the content we of course need to use the correct syntax to Output that value but now that we know how this is going to work we can then start to refactor our application so that the page viewer can go out and fetch the appropriate page so that it can then display that content and we will get started with that in the next lesson in the previous lesson we discussed how we are going to get data into our page viewer component we are going to rely upon the URL to give us the index of the page that we want to display so that's inside of the page viewer component we will just fetch that page and we can then display the content so the question then becomes how do we go about doing this well the typical pattern is to use a centralized data store and ideally we would use a data store that is reactive meaning that anytime that there were changes made to our data either by editing a particular page or creating a new page and adding it to the data store then the application would automatically update to reflect those changes and there is a data store available that does exactly that it's called viewx and we aren't quite ready for that so instead we are going to use a poor man's centralized storage and that is basically we're going to write it ourselves and it's going to be just simply an object that gives us access to our data so in this particular implementation anytime that we make changes to our data we will then have to tell the application hey the data's changed it's time to reload all of the data thankfully we have a global event bus that can help facilitate that so the first thing I'm going to do is create a file just called data.js this is going to signify our data store and I guess really before we start doing this I want to take the content of our pages.json and I want to go ahead and load that into the local storage in our browser so I'm going to pull up the developer tools go to the application Tab and for local storage for this application I'm going to add a new item let's call this simply pages and then the value is going to be that Json structure so that then we can load that parse it into an array and then we will be good to go there uh one thing I should point out is I am switching browsers I have been using Microsoft edge up until this point and I ran into some issues with Edge not navigating in between our different components Chrome did it just fine no idea why I spent a little bit of time troubleshooting couldn't really find the issue so I've switched to Chrome because Chrome was actually working when Edge wasn't I'm sure that there's a Microsoft joke there but we're just going to move on okay so for our data store I want to store the key that we are going to use to access the local storage as a variable so I'm just going to create this as a constant that way we don't have to worry about me mistyping a string which is something that well I would definitely do and then we're going to fetch the Json from our local storage so so let's go ahead and do that with the get item method we will pass in the pages key that we just created that will give us our Json so that then we can parse that into our array I'm going to call this simply Pages store and we will call the parse method on Json pass in our Json structure and we will be good to go to use that so I don't want to make this array directly available to whatever is going to be consuming this data store so instead I want to provide some methods that are going to wrap around it this first method well it's not really going to give us much of anything as far as protection is concerned because all this is going to do is return that array so whatever we're gaining by trying to protect this we've kind of lost just by returning this but that's okay for now and then I want another method that we can use to retrieve a single page all we need to do just provide the index and then we will return that page at the given index ideally we would have some kind of validation to be sure that the index is valid and that we do have something at that index but we're just going to keep things simple and go from there so this is our data store we're going to make this available just like we did with our event bus so we can import this we can call it uh let's call it dollar sign Pages because that's essentially what it is and that is inside of our data files so that we will make this available as a global property we'll call it dollar sign Pages again and there we go so this is going to give us access to our data store directly inside of our components so now we can close all of these other files let's leave data up in case if I need to fix any issues there and let's go to page viewer because this is where we are going to be displaying that page so inside of the created hook sounds like a pretty good place to fetch that page so let's say that we're going to have a data property inside of this component called page and then we will use our Pages object so that we could get a single page and then we want to get the page at the given index at the provided route so we will access the route params and we want that index value so with just that change although no that's not just that change we do need to define the page and let's initialize this as no that way whenever we display our components we can use the V if here to check to see if we have a page and if so then we want to go ahead and display that information otherwise we would want to hide it so that we don't run into any errors there so we want to Output the page title as well as the content so let's add that back as our output let's go to the browser and let's see this in action we have an error reference error Pages Json not defined that is inside of data.js and so Pages Json I'm glad I left that file open it's amazing what One Missed keystroke is going to do so let's go back and there we have it we can see the content for our home page now if we click on about nothing is going to happen of course because we have written nothing that is going to display the information because we haven't set up our application to actually navigate using the router so we can do that by going to the navbar link and instead of outputting this a element instead what we want to use is called router link it's a component that's automatically loaded for us so that all we need to do is just use this router link it doesn't have an href attribute instead what it has is a two attribute and then we specify the path that we would want to go to so in this case it would be a slash followed by whatever index so we want to bind this then so that we can dynamically generate this using JavaScript so our URL is going to include the route params index here so it doesn't matter what component that we are in the route is going to be the same as long as that component is displayed and then we want the index there so that should give us our link uh let's see we don't need the click event this is of course going to break some things but that's okay and in fact in this particular case it's not because this it was for telling the app component that this is the active page so we don't need that now everything else should be okay I don't see any other errors now as far as tracking the active page it's going to be a little bit different now because well as you can see that's not working but you can also see that we aren't actually navigating to those different pages as well and the reason is very simple it's because the page viewer component is already loaded so here's the thing about navigating using the view router if you navigate to a different component then everything's fine you don't really need to do anything extra however if you are navigating to a component that is currently loaded well then you have to tell your application hey the route parameters changed so load new data into that component now we can first of all demonstrate this by adding a link to our create page so let's do that inside of navbar because that's where we build the links based upon our Pages now we're going to add another link for the create and I want to make sure that we use all of the right CSS classes so let's copy this router link and let's paste that into navbar because a lot of this is going to be the same because we still want to use a router Link in this case however we can use just a straight up normal to prop here to where we want to go to slash create now let's get rid of the class binding for active classes because that doesn't mean anything here we don't need the href either in fact we should get rid of the href in the navbar link so let's do that and then the title we don't need and as far as the text of this let's just have it as create page so with those changes done let me make sure all of the files are saved we can go back to the browser and now we see create page so we are currently at the page with an index of one which is about but notice that we are still displaying home page but if I click on create page we see well it navigated whenever we click on about we see about if we click on home we don't see that if we click on page and then go back to home then yes the content changes so as long as you navigate to a different components you don't really have to worry about anything if you navigate to the same component then we have to tell the application hey you need to update and the way that we can do that is with a Watcher in fact there's two different ways that we can do that and we will look at how in the next lesson in the previous lesson we set up the page viewer component to actually display the content of a page we created a makeshift centralized data store that gives us an easy the ability to fetch the page based upon the index and then we display that information but there's a slight little problem if we navigate to a page that uses a different component then everything works fine but if we navigate to a page that uses the same component such as the home and about links both of those use the page viewer component and notice that even though I'm clicking on them and the values and the URL changes the content doesn't change and the reason is very simple the page viewer component is already loaded into the application at this point and it's loaded with whatever page content we first navigated to so I went to the create page then I clicked on about and that's the content that we see so even though the route params change the page viewer component doesn't necessarily know that it changed and and that it needs to update the page appropriately so basically what we need to do is use a watcher we need to set up a watcher so that the page viewer component knows when the params change and then it will load the new page when that occurs so great we've written Watchers before so we will add the watch option and then what do we use here for the Watcher name because this would normally be some kind of simple identifier it would be a data property like page in this case or it might be a prop name how do we do something that is Reliant Upon Our routes dot rams.index well we don't at least we don't use the watch option instead we can set up a watcher programmatically using the watch method actually it's dollar watch and the concept is somewhat the same the first argument that we pass to the watch method is a function and the return value is whatever it is that we want to watch so in this particular case that would be our route params or we could say that we just wanted to watch the index on our route params but if this was a component that relied upon multiple params it would make a whole lot of sense to just watch for the params itself so that when that changed then we could update the data and that's the option that I'm going to go with here okay so that first argument is the function that returns whatever it is that we want to watch the second argument is the function that is going to execute when the params change and in this case it starts to become very much like any other kind of watch implementation so that we have two parameters here the first are the new params the second are the previous params and then inside of this function we just do whatever it is that's we needed to do which in our case is to change the value of our page so that once again we use our Pages data store to get the single page for the index that is provided by the new params and so there we go by Saving this we will be able to go to the browser and we will see this work so we see that it switched to home page if we click on about uh we get an error that's because dollar sign this does not exist yeah of course it doesn't so let's go back let's clear out the console and now let's click on about okay let's refresh the page and now let's click on about which was already loaded because that's what the URL was but if we click on home we can see that the content changes if we click on about I mean we can click back and forth all day long and that content is going to change if we click on create page that still behaves as it did before so this is one way that we can go about uh setting up our components to respond to when the params change the second way is a little more straightforward and it's a lot more familiar and that is we can essentially tell our application that for this route the route that's using the page viewer we want the params to be passed as props to do that we pass in another option simply called prompts and we provided the simple value of true so so now the value of index is going to be passed as a prop now this means that we need to Define that prop so let's go ahead and do that we don't need to do any kind of validation we can just use the simple declaration and then we just need to update our code appropriately so that inside of the created hook we just use simply this dot index to refer to our index and now that we have a simple identifier we can use the watch option so that we can watch for index to change we have the new index and the old index so that's now we can simply set our page data property to the page with the given index so let's just copy and paste and use the correct variable name same idea but it's a bit more familiar so let's go back to the browser let's refresh the page home page is loaded it we navigate to about we navigate to home about once again everything works as it should now there's no right or wrong way to go about this you can use whichever option that you want if you want to Define The Watcher programmatically and use the route params then feel free to do that if you want to use the more traditional and more familiar approach of using props you do need to tell the route to use props props is true that will pass the params as props so that it gives you a little bit easier access to that data and you can use the options to Define your Watchers well in the next lesson we need to address the active link because now that we are using the view router and we are loading this content differently how we handle the active link is of course going to change and we will look at that in the next lesson I think it goes without saying that if you want to provide navigation for your application then you need to use view router because that is after all what its purpose is but one of its features is to keep track of the active link which is something that we have done on our own and I guess technically we haven't kept track of the active link we've kept track of the active page and then applied the appropriate CSS for the link associated with that page which meant that we had to plumb our application to track that particular value well that's built in with view router and in fact it's based upon the URL so instead of keeping track of something internally it is looking at the URL and matching that to the paths that we have defined inside of our routes and so then it knows what link is active the only thing that we need to do is tell it what class that we wanted to use when a link is active so let's go to our navbar link and this is going to greatly simplify our navbar link as well as navbar and app so in navbar link we are using this active classes object this was a computed object that allowed us to set both the active and emphasize classes I want to get rid of the emphasize just because I don't really like how it looks but we'll use it first so that you can see that it is indeed working and then we'll get rid of it so all we have to do is add a prop called active class and then we provide the CSS classes that we want to apply to the active link so in this particular case that would be active and then emphasize so let's make that very simple change let's go to the browser and we are on create which we did not add that active class prop 2 but we will here in a moment but if we click on about we can see that the active classes are applied if we click on home the same is true now to prove that this is based upon the URL I'm not going to click on about instead I'm going to change the url so that instead of the index 0 we're going to use the index one I'm going to hit the enter key and voila we can see that the active link changed so I'm going to get rid of that emphasize which means that we can get rid of this style it also means that since the active class is being handled by the router we don't need this computed object of active classes so we can get rid of that now the active classes object used this is active prop well we don't need that either so we can get rid of that so that this component is only going to use the page and the index and that's it I think that's it that's all that we need so by just using the active class prop on the router link we were able to greatly simplify this component so that's one let's close that let's go to navbar so our navbar link this was generating the links for the pages we need the page we need the index we don't need the is active prop so we can get rid of that we don't need the activated event so we can get rid of that to the create page link we do want to add that active class so we will set that to active and everything else will be fine so let's take a look at our props because we did manage to clean this up so that we don't need active page anymore in fact let's search let's make sure that we aren't using that anywhere else it looks like no we're not so we can get rid of active page so that this is only relying upon Pages which that is something that we can change as well but we'll get to that here in a moment let's make sure that there's nothing else all of these are for the theme so we are good there so now let's go to the app component because this is where that active page was being passed in so we don't need that either which means that we can get rid of our data in fact we can get rid of the created well at least for the most part because uh we we're listening for This Global event of navbar Link activated that was primarily so that we could set the active page you don't need that anymore so we can get rid of that we can almost get rid of our data if it weren't for the pages array which well let's go ahead and let's get rid of that let's also get rid of the created hook because we aren't going to need that let's get rid of the get Pages method I will keep this page created just for the time being we will probably get rid of that at some point later now the reason why I'm getting rid of the pages all together inside of app is because now that we have our data centralized the nav bar can load the pages itself so let's go back to the nav bar and we are going to add pages to our data we don't need it as a prop anymore we do want to initialize it as an empty array and then inside of the created hook we will simply get our pages from our data store so that is using the pages object I believe the method was called get all pages we will find out if that is indeed the method or not but that should be it we could go to the browser let's do a hard refresh make sure everything is loaded from scratch the about page is currently active we click on home that works about create and we still have our navbar so the pages are properly loaded and the nav bar is generated so everything is working as it was we were able to clean up three components by just using the active class which I don't know about you but to me that's huge and then by changing the nav bar so that it pulls in the pages so that it can generate the appropriate links so that we can clean up the app component that was also a nice little side effect as well well in the next lesson we are going to look at nested routes so far the routes that we've had are very simple and simple is good but in real world applications we usually deal with more complexity and nested routes give us the ability to handle that complexity in this lesson you are going to learn about nested routes which are exactly what they sound like they are routes that are nested inside of other routes and you want to use nested routes when you want to build a UI that is structured third in such a way that the components mirror the URL like for example let's just think in terms of typical web applications where we are working with an individual resource in the case of our application our resource our Pages we have a URL for displaying the content of individual Pages all we have to do is supply the index and we see the content but let's say that we wanted a management section so that we can manage those pages well within a typical web application the URL would be slash pages and then from there we would have a structure representative of working with pages so that if we wanted to create a page then the URL would be Pages slash create if we wanted to edit an existing page it would be Pages slash the index number slash and then edit and if we wanted to delete it would essentially be the same thing except that the last segment would be delete so this is a very structured URL and we can translate these URLs into a series of routes that are nested inside of one another so if that's not clear which I'm not sure it's even clear to me the code makes it very clear so what we're going to do is create a route with the path of Slash pages and this is going to be handled by a component that we would call just simply Pages now if you look at other people's projects you are probably going to see a folder called views the views or at least what are considered views are the components that handle routes so in our case we have the page viewer we have the create page those are essentially views because they are handling routes so I'm going to create a new folder called views and I'm going to move those components into the views folder now this is not necessary this is just convention but it's a good idea to follow convention so I'm just going to drag and drop those I do have a plug-in for visual studio code called V2 feature I I don't know I don't know how to pronounce that but this is going to find where those files were referenced and it's going to automatically update the paths so whenever I click on OK this is going to modify the routes file uh why did it modify app oh because we still have those listed there we don't need these inside of apps so we can delete those because now all app is is a container basically for the router view which is essentially what we are going to create with this Pages component that I've just talked about so let's create a new file inside of the views folder we'll we'll call it pages.view and the template is going to be very similar to our app component in that we'll have a div with a class of container and then we're going to have a heading because this is going to serve as a container for all of the nested routes so I want this to say page management so that all of the child routes that we are going to visit are going to have this H2 element in them so that we can see this is part of the page management and then we will have our router view so this Pages component that we just wrote this is going to be loaded inside of app.view so it's going to be loaded right here but it has its own router view so all of the child routes are going to be rendered here it's part of why this is called nested routes you'll see the other reason why it's called tested routes uh well right here so I want to make the create route a child of our Pages route and we do that by just adding another property to this route object it's simply called children it's an array of other route objects so we can just cut and paste uh the path does not need the beginning slash for child route but that is going to work we do need to import this Pages component though so let's go ahead and let's import that and whenever we go to the browser uh let's let this refresh let's go to Just slash pages and we see page management that is the pages component that we just created if we go to Pages slash create we still see page management because that is the parent route that is essentially handling the pages part of the URL but then we also see the form for creating a page that is handled by the create part of the URL but let's also say that if we go to Just slash pages I want to see something here it makes sense to list all of our Pages we aren't going to actually list those just yet but let's go ahead and let's create the component that we can use to eventually list that so to do this our path is going to be just an empty string so this will essentially be the default of the pages route let's call this component Pages list and of course we need to create that file and as far as its template is concerned let's just have some content something to say that this is the list so let's have a p element this is the pages list let's move this into the views folder and then we want to import this as well inside of routes so we will have our Pages list so that now whenever we go to the browser we will see the text for this is the pages list that's going to be the default for going to Pages whenever we click on create page which that we need to update that link don't we that is inside of navbar so instead of going to just create we need to go to Pages create and I guess ideally we should turn this into a menu so that we have all the options available so whenever we go to Pages create we see the page management we have the form we don't see the default text of displaying the list but that's because we aren't at just Pages we are at Pages create so in the next lesson we can start to build our other components to handle those nested routes and we will do so using the composition API the composition API was introduced as a plugin for view 2 and starting with view 3 it is baked into the framework and we have the composition API because of react function components in fact if you look at the documentation for the composition API it's very clear it says this was inspired by react and I feel like I need to give you just a little bit of background on react components because it gives you an idea of why the composition API exists and why you would want to use it so in react you can create a component in two ways you could write a class or you can write a function although originally the only way that you could go about it was with a class and it would of course have all of the functionality that you would need within a component it would have States you could have methods and it could be very complex but then they created function components and originally function components were just very simple you essentially fed them data and then they would output that data they might manipulate it but the manipulation was only for the output there was no State there was nothing they were just very very simple well people liked using the function components so they wanted to essentially do the same things that a class could do so in order to facilitate that functionality they created what they call hooks they are just basically functions that you import and you would use the hooks that you needed within that component so if you needed State then you would import a function to use that state if you needed some other functionality that was provided inside of a class there was a hook for that so you just imported that function and used it and then there you go so the composition API in view was based upon that idea except that they did a much better job of it not only are they easier to write at least in my opinion but they also perform better because there are some performance issues with a function components in react and Views composition API is also much easier to understand and follow than reacts functional components there are just some things that you have to think differently in order to use those features and with views composition API you pretty much don't so what we're going to do is look at the differences between the options API which is what we've been using thus far where we export default object and then we will do the same component but with the composition API so this is of course the pages list component but we're going to use it for this example and then we are going to actually well list our pages so this is just going to have a simple counter we'll click on a button that will call the click method and it will update the counter so for the options API we would need the data which we have to Define as a function function which returns an object that then has the data that we want to work with so counter we will initialize the zero but then we have that click method now we could simplify this to where right here we just increment counter and that's fine I want to do this to where we say that we have this click and we would need to Define that as a method but to do that we have to first of all have the methods option then we would Define click and then we can update our counter whenever we click on it so whenever we go to the browser we are going to see uh well let's add some text for the button so that we can actually click on it and whenever we click we see that the value changes there's nothing out of the ordinary here but there is a lot of boilerplate involved we have to export an object we have to define the data method that returns an object we have to use the methods option if we have any methods the same is true for computed values and Watchers and by organizing our code into these different little sections the overall functionality and flow and logic is kind of disjointed because our data is up here our methods are down here and it's not that bad with this particular component because it's very simple but in a very large component you're jumping all over the place in order to change the data okay I need to go to the method now and change this okay now I need to go to the computed it just it it could be a lot better and that's what the composition API aims to achieve to organize to give us the ability to organize our code logically so to use the composition API we need to add the setup attribute to our script element and the reason why is because in the version two we would have to define a function called setup which was used for setting up the code for our component and this would also need to return turn an object that contains the things that we would need to use inside of our template so if we wanted to use counter and click we would have to return those in an object wasn't that difficult but it was more boilerplate that we had to do but now we just have to use the setup attribute on the script and then we're good to go so let's start by creating a counter variable and then we will just Define a function called click to where we will increment the counter and whenever we view this in the browser it's going to look like it's going to work we see the value of 0 we have our button but whenever we click nothing happens well behind the scenes the value of counter is changing in fact we could write that out to the console and we could see that's being updated but it's not going to be updated within the browser because we are using just a simple variable it's not reactive so behind the scenes view doesn't really know that this value is changing it's not going to update the component in the browser so instead what we need to do is tell view that this value is reactive and we can do that in one of two ways we are going to use a hook so we have two that we can use one is called ref the other is called reactive you can use one or the other but there are some things that you need to be aware of first we'll talk about ref ref allows us to create a reactive value that value can be a primitive value like a number or a string or a Boolean value or it can be an object or an array or anything but we're going to use just a simple numeric value now whenever you do this we have initialized our reactive variable counter with a value of zero we can also do this because behind the scenes what we actually end up with is an object that has a value prop property and it's going to be initialized with zero so this means that inside of our code or inside of our script we have to use the value property anytime that we need to update that value so in the click function we would use counter.value and we would increment that but inside of our template we don't have to use that value it's automatically implied so with that simple change we can go back to the browser and whenever we click we can see that it does indeed increment so that's one way the other way is to use the reactive hook I'm going to create another variable and I'm going to call it data and the reason is because whenever you use reactive this is not for primitive values so you can't use a numeric value a string Boolean anything that's primitive is for anything that is based off of object so it can be an object an array even a function anything that is considered an object you can use reactive for so this is very similar to the concept of data at least in my opinion so in my code what I would use is just simply the name data so that I could define the properties that I would need for my data which in this case is going to be counter this changes our code though so that inside of Click we would need to use our data counter and then increment that and then inside of our templates we would need to prepend counter with data but other than that everything else is going to work just fine and of course we could simplify this just like with the options API so that instead of defining this click function we could say data counter we could increment and we would see the same functionality and the same is true for using ref if we wanted to go that route as well so this is the primary difference between the options API and the composition API there is a little bit of boiler point because we do have to import the functions that we need to use of course we will talk about the other functions such as setting up a watcher setting up computed values even using a life cycle event but it makes our code much more logical makes it easier to read and understand what's going on behind the scenes and it can be much more concise as well so in the next lesson we will start to implement the pages list foreign I introduced you to the composition API which is a different way of writing components it takes a more functional approach as opposed to the object-oriented approach of the options API now we have the pages list component and we want to display our list of pages so that one we can see that list and two so that we can navigate to a dedicated edit page for each one of those pages so we need our list of pages here and the question becomes how do we get that data because currently our pages are provided as a global property it is available to the components using the options API we use this Dot and then dollar sign Pages we did that in both the page viewer and the nav bar but inside of our Pages list which uses the composition API we don't have access to this or at least this doesn't refer to this component so we can't access pages in that way now we can import some functions and we can get to our Global properties but it's not very straightforward and in fact using Global properties really isn't the best way of providing information to components that are deeper in the application because this is really just an escape hatch this was to provide the same kind of functionality that was available in view too in view two we were able to add Global Properties by just adding them to views prototype but with view 3 that was taken away and the global properties were then provided to replicate that functionality but there's a better option we can provide information that we can then inject into child components now let me first of all say the primary way that we get data from a parent to a direct child is through props there is no better solution there unfortunately for us Paige's list really isn't a child it is a view that is going to be displayed by navigating through the router so we can't really pass props here but instead we can provide our Pages object so I'm going to comment out this line because we don't really need that after we do this we will use our app object we will call Provide and this accepts two arguments the first is the key that we need to refer to our Pages which I'm just going to continue using dollar sign pages and then the value associated with that key which is dollar sign pages and this is essentially going to provide our pages to the app component and all of its children so for all intents and purposes this is providing a globally accessible object that we can access from any component but we can provide anything from any component and it will be available to all of its children it can be a direct child or it can be one that is farther down the hierarchy so this isn't an automatic thing what we have to do is go into the components that need access to this and we need to inject our pages so the first one is inside of our page viewer we will use an option called inject and then we simply provide the keys that we want to inject here that's going to be dollar sign Pages the rest of our code is going to work just fine because this becomes a property on this inside of the component we will do the same thing inside of navbar and then we can do a sanity check and make sure that everything is working as it should so let's add that inject I'm going to do it higher up in the object definition because to me that's kind of important and whenever we view this in the browser everything should still work let's do a refresh and our navbar is displayed we can go to about home and create page everything works there let's get back to our Pages view so now we want to be able to get this dollar sign pages and we do that by first of all importing the inject function and then we will get access to our Pages by calling inject and then passing in the key that we want to access in this case dollar sign pages so that we can then use this to generate our list so let's have a subtitle here because all of our Pages inside of the pages child routes are going to have this page management so I want a subtitle let's use an H4 and let's set the text to just simply Pages then we will have a table and let's use the table class we'll also want this to be striped and let's also use the table hover class and let's define the head of this table let's just have three columns we'll have one for the title one for the link text and then one to signify whether or not the page is published we don't necessarily want to display the content here because if it's a lot of content well that could be a lot to display so then we need to generate our body we'll use T body first and then we want to generate a table row we'll use the V4 directive and we want to work with the page and the index that is given to us from our Pages dot get all pages we of course need to set up the key so let's use the index for that and then we just want to display the column information such as the page title the link text and then whether or not the page is published so with that we should be able to to go to the browser and we should see our list but I want to change this is published I don't want to use true or false I want yes or no so we can easily change that with a ternary expression and I want to be able to navigate to The View that enables us to edit each one of these Pages which that's something that we will do in the next lesson but to prepare for that I do want to add a create button because I want to take out this create page link because to me it doesn't make a whole lot of sense to have that there instead it makes more sense to have our Pages linked so that we can see the page list so let's change that link so that it's going to just slash Pages we'll change the text so that it's pages and then we will add that button inside of the pages list view we can just use the div let's align the text to the end and then we will use a link to get us to the create so we will use our router link component we don't have to dynamically build this URL so the path will be just simply slash Pages slash create but let's make this look like a button so we will use some of bootstraps classes to make it look like a button we'll have the button and then the button primary let's also use the button small class so that it's not too big and then uh we'll have the text of new page so now there's our new page we should be able to click this that takes us to the create page that works just fine we have our list of pages and now we just need to be able to create our edit view for each one of those pages and we'll get started with that in the next lesson now that we have our list of pages I want to be able to navigate to the edit view for any one of those pages and of course the most straightforward thing that we can do is use the router link component we can turn the titles into links that the user can then click on and then there they go but I want to make this so that the entire row is clickable if they click anywhere that's going to navigate them to whatever page is associated with that row now of course the TR element doesn't have an href attribute it doesn't behave like a link so we are going to have to write the code to do that which means that we need to handle the click event and we can say that we're going to write a function called go to page where we pass in the index of the page that we want to go to so we can go ahead and we can start writing that function but we're going to hit a brick wall here pretty soon because well how do we navigate using JavaScript and the answer is very simple we just use the router so to get access to the router we need to import a function called use router from view router now we haven't specifically accessed the router before using the options API we did access the route so that we could get to the params and I believe that was inside of page viewer yes it is so we used that dollar route property in order to get to the params well we could do the same thing to get to the router if we needed access to that and once you have access to the router then the API is all the same so we want to navigate to a different page that is going to be the edit view so we need first of all the router we're going to call the use router to get access to the router and then we're going to call a method simply called push we are pushing in the path of where we want to navigate to and in this case it is going to be the pages is and then the index of the page and then edit very simple and straightforward and then by clicking on the TR element it's going to navigate us using the router to that particular view now of course we don't have that view so let's go ahead and let's define that we'll call it edit page or no let's do this everything begins with pages so or page so let's say page edit Dot View let's have our template for right now we'll just have some text that says edits page and then of course we need to add a route to this view so let's open up routes we need to import this component so let's do that and then we want to add this as a child to our pages so we're going to add another entry to the children and the path is going to be that simple path of the index program followed by edit and then our component is going to be the page edit component so with that in place we should be able to click on any one of these which you know it doesn't really signify that we can click there so let's change that let's go to our Pages list and let's add some style we can make this scoped to this component because really we wouldn't need it anywhere else and we want to add some styling to the table that has the table hover we want to do this on the TR elements whenever we hover over it and we are just going to change the cursor to the pointer that typically signifies that this is something that you can click on so that's going to work there let's also get rid of the striped because since we have hover we don't necessarily need striped because the striped is there to make it easier for the user to see what data is on which row but whenever you have the hover we we don't need that at all so whenever we click on this about page we should be taken to the edit page the URL is what it should be it is Pages slash one slash edit if we click on home page that should be Pages slash zero slash edit so yes this is indeed working so that's great now we need to be able to get the param information from inside of our page edit so let's start adding our script for that we'll use the setup attribute and we know that we can get this data in one of two ways we can get it from the params from the route or we can Define that the params will be passed as props let's look at both so let's add the props equal to true for that particular path let's go back to page edit and the first thing that we will look at is getting our props so there is a built-in function that we can use without having to import anything and it is called Define props and it works a lot like the props option in the options API we can pass an array that contains the strings of the props that we need so in this case that would be index and then from there we can use our props as an object to get our index so by Saving this let's go back to the browser um let's refresh and that says edit zero if we go to the about page edit one and of course contact is edit two so that all works but let's look at how we can do the same thing if we don't want to use the params as props the first thing we need to do is import the use route function which is from view router and then we want to get the routes which is essentially the dollar sign route property that we would use inside of the options API and we get that by calling that use route function so that then from there we can use the route to get to the params and then get to the index which whenever we view this in the browser let's just do a refresh we see once again edit 2 for the contact page if we click on home page edit 0 click on about edit one so the composition API doesn't hinder us really in any way we might have to write a couple of lines of extra code in this case to get the route so that we can get to the params but that's arguably negligible and so in the next lesson we will implement the edit View we are finally to the point to where we can actually start working with our data and we will begin in this lesson by implementing the edit view now we have a lot to do so I'm just going to jump right in and the first thing I will do is paste in the markup for the edit form now this is almost identical to the form in the create page view which is also something we need to fully implement but there are two differences the first is that there is not a link URL field because well we don't need that now that we're using view router and there's also a cancel button so those are the two changes and let's just start with our JavaScript now as far as our index is concerned I think it's easier to just get that from our props because we are set up to do so and we can destructure our props so that we just have direct access to index which can't beat that now we will need the router so I'm going to change this import statement so that we import the use route router and we'll go ahead and get our router but we also need the inject method from view because we need to be able to pull in our Pages data store so let's go ahead and let's do that we'll just call it pages and the key that we want is dollar sign pages and then that is going to give us the ability to just get the page object that we want to work with so we will use pages I think it was called get single page and we will pass in the index so this page object that we get is what we can use to tie into the individual Fields within our form you know we have V model in in the past we've just set that to an individual value within our component but we don't have to do that we can also set up the V model so that it is bound to a property on the page object so the page title property will be the V model for the page title field and then the contents property will be the V model for the content the same will be for the link text except that that is link.text and then finally the published and this is going to make our lives so much easier because we get the functionality of V model but then we don't have to make any changes to the page object because that was automatically done by V model so we're all good there now there's one thing I wanted to do and that is change the title I believe we used an H4 in the pages list so we'll do the same thing here we'll just say edit and then we will use the page title so that when it comes time to actually save this for the edit button let's listen for the click events we will of course prevent the default action and we'll just call this submit and then inside of submit we will do this it's going to start off fairly simple in that we will use our Pages now we don't have this method yet but let's just say that we'll have a method called edit page to where we can supply the index and then the page object that we want to save and that'll be it at least for now so that means that inside of our data we need to implement that function so let's do that we need the index and the page and we need to do two things here the first is to update the pages store array so that at the given index we now have that page object but then we also want to store this in local storage so that it persists between refreshes so we'll call set item we want to use that Pages key as the key and then we'll use the serialized Pages store as the value so that should work and with that done we should at least have the basic functionality so that's let's go to the browser let's uncheck published here for the edits page let's also pull up the console so that if we get any errors that we can see that and let's click on the edit button now it looks like nothing happened but really that's what we want because we we don't have any interactivity or any reactivity I should say so let's refresh the page and the about link should be gone it is so it's working at least as far as editing and saving this information so let's make it published again let's refresh so that we can at least see the about link there so we have the basic functionality but now I want to make it so that whenever we save a page it's going to reload everything that relies upon those pages and I think really the only thing is our nav bar because it needs to reload the published Pages here in order to generate those links so the way that we can do that is by using our Global event bus I mean we have that so we might as well use it so that's whenever we submit the form what we could do is use our bus and we would use the emit method to where we could say page updated and then we can also Supply some information about the page that was updated now not everything would need this information like for example the nav bar wouldn't really care what page was updated it just needs to know when the page was updated so that they can reload the pages but this way for anything that needs this information we can supply that because it's easy enough to do now of course we need that bus and currently it is set up as a global property so we will essentially do the same thing that we did for the pages so that's we'll just have dollar sign buses for the key and then dollar sign buses for that value so that's inside of page edits we can inject that just like we did the pages so let's do that we'll just call it bus because we already have the code that's going to do that and then we need to listen for this event inside of navbar so let's open up navbar and we want to in inject dollar bus as well and then we went to set up the event listener for that page updated so we can do that right here inside of the created hook so where we would use our bus and we will call the on method we want to listen for page updated and for the function that's going to execute all we need to do is update our Pages this is the pages data property inside of this component with the new pages so that should work right well it's not and we'll talk about why here in a moment but let's first of all prove that it doesn't work so I'm going to unpublish this I'm going to click on edit we don't get any errors and it doesn't look like anything words but whenever we refresh the page about is gone in the nav bar so let's talk about why the navbar didn't automatically update and it's really very simple and it's because of this right here when ever we set Pages originally we did so by calling get all pages this is returning that array that is inside of our data so this array object never changes the data inside of it may change but the array object itself never changes so inside of navbar whenever we set the pages data property to get all pages it's watching that array object and even though we update the contents of one of the objects inside of that array it's not watching the individual objects it's just watching that array now if we added an item to the array then yes it would recognize that this array changed but it's not watching the individual objects inside of the array so what we can do then is this we can assign a new array to the pages data property inside of navbar and then we can fill it by spreading out the array that we get from get all pages so we are creating a new array object we are populating it with the elements from get all pages and so every time page updated occurs then it's going to be a new array and that's going to tell the navbar component that hey the pages array changed it's time to fetch that information and update what's in the browser so with that change we should be able to click on publish now click on edit and we see about appear and if we unpublish it click on edit that goes away so now the only other thing that I want to do is navigate back to the pages list whenever we click on edit or whenever we click on cancel because we need that functionality so that whenever we edit a page of course the page will be edited but we need to navigate back to to our Pages list and we already have our router so let's do this let's write a function called go to Pages list we will use our router we will push in the path to the pages View and then we can call go to Pages list inside of submit so that after the page is updated after the event is emitted then we will go back to the pages list and then for the cancel button we can handle the click event using that to go to Pages function so now let's test this out again let's unpublish about we click on edit we go back to the pages list but I want to add contact so let's go to contact let's publish and let's edit but of course all we've been checking is published so let's change the content of the contact page we'll say contact content goes here let's save it let's navigate to contact and well yes there is a bug because we are relying upon indexes as opposed to actual IDs so that is actually correct at least as far as the code is written we need to go to index two because that is the actual index so here we can go to contact we see that content goes here so let's pretend that that bug doesn't exist let's unpublish contact let's go to about let's publish that let's change the content of about let's just say about page and so now whenever we go to about our edits are indeed updated so we now have the functionality for editing pages in the next lesson let's implement the code for creating a new page we need to revisit the create page view because we haven't done so since we started using the view router and we centralized our data store so I want to transition this from the options API into the composition API because this is going to give you the opportunity to see how we can Define computed values as well as Watchers but we also need to discuss what is and isn't going to transfer over because like the page created event is not if you'll remember the create page view was a direct child to the app component and we used the page created event to tell the app component that hey this page is created so that you can add it to the pages array but now the create page view is rendered thanks to the router and we will need to use our Global event bus to tell the rest of the application that a page was created so we don't need this emits anymore we will still need our event bus but we will get to that so as far as everything else computed data or methods and our Watchers everything else should transfer over just fine with a few notifications so let's go ahead and Define our scripts for our setup and we will start with our data now we have two options we can create individual variables and use the ref function to make them reactive or we can use the reactive function and then make this entire object reactive now it's a little tedious but I'm going to opt for the ref approach because I would prefer to just work with simple variables as opposed to having to use an object to get to the property that I wanted to work with so we're going to import ref from view then we will define those variables Now by taking this approach it means that we don't have to make any modifications to our templates because the V models for all of these fields are just simple values so we're good to go there although let's get rid of our link URL because we don't need that anymore so now that we have our data let's just get rid of that data option so that we can keep track of what we have and haven't implemented and the next thing can be the submit form so let's just cut that out let's paste that into our new script element and of course we will need to make some changes here the first is that we no longer are using this we have just simple variables so we can get rid of this dot on just about everything but in this case we need to get rid of Link URL we can also get rid of these lines that reset the form because I want to follow the same behavior that we did from the edit form so that whenever we create a page we just take the user to the pages list so we will also need to import the use router function so that's we can get the router and we can navigate so let's go ahead and do that so that I don't forget to do that later and we will also need our event bus so we can inject that and since we're doing that we might as well go ahead and get our Pages as well because we will need to interact with our data store and so when it comes to emitting this page created events we will need to use our bus here and I'm going to change the name of this event because for our edit view I used a hyphen to separate the two words since this is our own event bus we don't have anything to translate between the different naming Styles between using dashes and then a camel case so instead of going back and changing what we did for the edit form I'm just going to make this one follow suit so we'll call the events page created we don't need this in front of all of these values in fact we can just simplify this by using the names of the variables although for the texts we will still need linked text but everything else should carry over fine and then before we emit this we will need to add this page to our data store so I will call the method add page we'll pass in a page object so let's do this we will create a page object we'll just call it new page set it to that object so that then we can pass a new page to add page and then we will do the same thing for the page created event and after that we will use our router to navigate to slash pages and so that should be that for the submit form function so let's get rid of our methods now our computed and our Watcher all we have to do is import a function called computed and another one for watch and setting up a computed value using the composition API is almost Zach well it's not almost exactly what we want to do is create a variable with the same name as the property that we used in the options API and then we will call the computed function this accepts a callback function that is going to do whatever it is that we need to compute which in this case was just checking the values of our form so we will essentially do the same thing let's get rid of this because we don't need this and that should be that setting up a watcher is also very simple we call the watch function we pass in the value that we want to watch which in this case was simply page title now there is some rules about setting up a watcher and that whatever it is that we are watching has to be reactive so that means the value has to be created by calling ref or reactive so keep that in mind but then we also pass in the Callback function that will execute when that value changes which we can essentially just cut out the code from The Watcher from the options API we do need to use the correct syntax here using our Arrow function and of course we want to get rid of the usage of this but other than that it's the same function and with those two things implemented we can get rid of the old script element altogether so that should be good let's go to our pages and not our Pages we need to go to our data and we need to add that add page is that what I called it it sure is so let's add add page and all we need to do is push this into our Pages store and then we need to save that so we will save it back into local storage and that should be that and then we need to go to our nav bar because after we add the page we need to be able to listen for that page created event so that we can redraw the nav bar so I'm just going to copy and paste change the name of the event and that should be fine so let's go to the browser and let's refresh let's see if we get any errors or Warnings everything looks good so for the page title let's just start typing we'll have new page now our linked text was not updating automatically and I know why that's because we didn't use the value property whenever we set the value for link text so we want to check if link text Dot value is equal to the old title in which case we want to set link text.value equal to the new title so let's go back to the browser let's try this out new page there we go we have that functionality uh let's change the link text and then let's change the title again we can see that it's behaving the same way that it did before so that's always a good thing but let's have the page title and the linked text as it's the same as far as the contents we don't care we just need some content let's make this published so whenever we click on this button it should add the link to the nav bar it should navigate us to the pages list and no we get an error add page is not defined now I know we wrote that add page is right there oh there we go uh yeah we need to push page there let's go back to the browser let's do a hard refresh and let's try this again with new page the content doesn't matter and let's click on create page and there we can see that new page was added to the menu the title and the link text are strings and now that I think about it I think I know why let's go back to our create page because whenever we create this new page we are using page title content a link text and published these are refs we need to add the value so this needs to be page title dot value and we will do the same thing for all of the other values it's always the little details that end up biting you so let's try this again uh let's change this to new page the contents the new page link text let's do something completely different and let's edit okay there we go that looks like it should but let's make sure that everything's okay we'll say new page content create page and there we go so now we have the ability to create Pages we have the ability to edit them we can navigate to those pages and deleting them should be very simple and we will add that functionality in the next lesson we need to provide our users with the ability to delete pages and we have a couple of different options when it comes to implementing this so we could add a delete button to the edit view which kind of makes sense because that would force the user to have to click on the page in order to then click on the delete button kind of like a a two-stage confirmation are you really really sure you want to do this another option would be to add a delete button to the pages list you know over on the right hand side so that they could just easily delete that uh we could go either way I'm going to lean towards implementing the delete on the edit page so let's add another button and ideally it would be completely separate from the edit and cancel but we're just going to keep things simple and put it right next to each other as far as the coloring is concerned I'm going to use the danger class the text will just be delete and then for the function let's call it delete page and let's go ahead and Implement that function which should be relatively simple because we have all of the information that we need we just need to interact with our pages and we could say that we have a method called remove page we would pass in the index and that would take care of that but of course we need to tell the rest of the application that a page was deleted so we can emit another event we could call it page deleted and the only information nation that we really need to supply would be the index I mean I guess we could Supply the page as well but I think index is going to be fine and really the only thing listening for this is going to be the nav bar so really it doesn't need to know but again having that information available could be useful later on now of course after we delete a page we want to go to the pages list so we'll make that the last thing that we do inside of delete page so we need to implement this remove page method so let's go to our data store and let's add this remove page we want the index and uh all we really need to do is splice out that item at the given index and then we want to save that now since we have saved data two other times let's just do this let's write a function called save to where we will save our data that will make things a whole lot simpler and really easier to read then whenever we edit a page we will save and whenever we remove a page you will say and then of course we need to listen for that page deleted event inside of our nav bar so let's go there let's set up another event listener I guess if we really wanted to spend a lot more time on our Global event bus we would add the ability to pass in an array of all of the events that we would want to listen to because you know in this particular case it really doesn't matter what happens if we do anything to our Pages we want to update our list of pages that are displayed in the nav bar so it would save some time if we could pass an array of strings for the events names but this is going to be fine so with that in place we should be able to delete a page so here we have the one with the index of four this is what the new page so if we delete this there goes that page let's try to delete the other a new page that's gone as well let's make sure that we are actually saving that data so let's go to the application the pages yep we only have three items there so if we decide okay we don't want people to contact us then that is gone as well we can refresh the application Tab and sure enough so we now have the ability to delete edit and create pages and it's all Dynamic the user interface updates for every change that we make and compared to what we would have had to have done in just normal JavaScript this was a whole lot simpler view JS is my favorite UI framework and don't get me wrong react angular and all of the other Frameworks do their job just fine but there's something different about view it's very easy to get started and it lacks a lot of the wonky rules that seem to plague other Frameworks it's my hope that by now you have a firm grasp of views fundamentals you know how to use most of use directives such as vbind V4 VF V show V on and V snow on you also know how to write and use computed and watched objects provide and inject objects into your components and provide functionality with methods or functions you know how to use the view router so that you can build Dynamic single page applications and you also learned about the new composition API so that you can better organize larger and more complex components Vue is a fantastic framework and I hope you continue to use it in your current and future projects thank you so much for watching this course feel free to contact me through Twitter or the touch plus forums if you have any questions from all of us here at tuts Plus thank you and I will see you next time
Info
Channel: Envato Tuts+
Views: 314,570
Rating: undefined out of 5
Keywords: vue 3, vue 3 tutorial, vue js, vuejs, vue js tutorial, vue js tutorial for beginners, vue router, vue js course, front end developer, vue 3 composition api, vue, vue js 2.0, vue js 2 components, vue composition api tutorial, vue composition
Id: 1GNsWa_EZdw
Channel Id: undefined
Length: 261min 58sec (15718 seconds)
Published: Wed Jan 25 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.