Build a Todo App With Angular - Angular Todo List Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello and welcome back to the channel in this video we will create a to-do application from start to the end in one single video using angular framework and it may sound like this is super small application but if we will build it correctly there are a lot of ways to see how angular can shine in creating applications so let's jump right into it [Music] so first of all let's look on the project that we will build so here i am in 2dmvc.com and the idea is that this is the same project with already prepared styles which will be built in different frameworks or languages and as you can see here we have a lot of examples of different frameworks for example here is react and this is how our project is looking like so here on the left part we have all sources and links we can ignore this because this is not a part of the project but here on the right we have our to-dos project so here is the headline and then we have an input with immediate focus so when i reload the page as you can see i'm already focused in this field now on hitting enter we are getting a new item here so we can just type something and hit enter now we see our to-do's that we need to implement and here on the bottom we have footer with information so first of all on the left we have the amount of items and here we have three filters so all active and completed so we can mark some tasks as completed and now as you can see here we can click on active and then we see only active tasks so our completed tasks are only being showed in completed filter or in all also we can of course remove from here our to-do's or add new if we want and here we have toggle all which means we are marking all our to-do's as completed or uncompleted so this is the application that we will create together and actually if you didn't watch my course angular for beginners or you think you don't have enough knowledge to build an application i highly recommend to check that video i will link it here on the top it has all basic knowledge of angular that you need to know because in this video i won't talk deeply about basic features i will just implement a project and just describe some things that will be interesting to start implementing this project we will use angular cli to generate a project so if you don't know what is this this is angular io this is a cli tool and here we can click get started and then jump to get started cli so the idea is that we can install globally angular cli and then use command line tool in order to generate our angle application but first of all you need to install node.js on your machine if you don't have it you can just jump in nodejs.org and download it here and i always highly recommend you to use lts version because it is more stable and to check if you have node on your machine you can just write in console node minus version and i'm getting here 14 something and actually if you have something higher than 10 you're good to go so node is there now we need to install angular cli for this you can just copy this command npm install angular cli but i won't run it in my console because i already installed it previously this is why after installation you can check with ng minus minus version and if you are getting here something like this it means that everything is installed correctly because as you can see here is information regarding angular cli so normally to generate an application with angular cli we're just writing in gene u and the name of the project and this is what you need to do now but in my case it will be a little bit different because i already have a folder as you can see here i have a folder it is completely empty i just have here a git and git ignore so nothing except of the git and the problem is that i can't really generate the project with engine u my app because i need to define here that i want to create a project in existing directory so what i can do is jump to the console and put here an attribute so as you can see engine u then the name of the project this is my app and here minus minus directory and here should be the path and for me it will be just a dot because i want to use my current directory and of course we don't want the name my app but for example to do mvc and i'm hitting enter and now we're getting some questions from angular so do we need angular routing yes of course this is why i'm hitting yes what stylesheet do we need actually we won't write any css because we will use already predefined css off to do mvc project now as you can see angular started to install all packages and at the end we are seeing something like packages installed successfully and the directory is already under version control maybe you don't see this message because you are not having directory with initialized kid which means angular will create git for you now we need to start our application so to start the application we are just running in the console in gserv now as you can see compiling is finished successfully and we are getting the message angular live development server is listening on localhost 4200. as you can see i opened localhost 4200 and here is the boilerplate of angular so this is actually a component of angular which is rendered by default and here as you can see we have to do mvc app is running so we're good to go if you are on this step when everything is generated and you started angular project with angular cli you are ready to start writing code and the first thing that i want to do is clean our project so let's jump here as you can see this is the files and the project that was generated by angular cli so here for us is interesting source app and here inside app we have our basic app component so actually if we will jump in app component css we don't have anything here and we can remove this file because we won't write any global css and i will also remove app component spectes and just leave this for files here now let's jump in app component ts and as you can see here we have a basic angular component with title property we don't need title property so let's remove this and jump in appcomponent.html as you can see here we have a placeholder with a lot of css and some markup on the bottom so i will remove everything completely from here and just will write h1 tag and let's close it now for example hello to do mvc now let's save it and look in browser as you can see here we are getting the error could not resolve app component css so actually we removed the file but we didn't remove the reference from app component yes so here we have style urls and this file is missing so we can remove it from here completely because we don't want to write any global css now when we look in browser we have hello to the mvc so everything is cleaned and we are ready to build our project our next step will be to add all global styles that are already prepared for us inside to do mvc project because we don't want to write css on our own and we need to focus on angular itself so for this we have a global file in source and it is called style css so actually as you can see here is the message you can add global styles to this file and i will paste here all css that is prepared in to do mbc and as you can see this is really a lot so we will use just classes and you can take the whole file from the description box below i will have the source code of our project there now let's check if it's working when we're opening a browser as you can see our h1 is already styled differently which means the styles are already there so as you can see here i can make it bigger and we have css for h1 which comes from this file our next step is to think about our project structure actually we have quite a small project but i highly recommend you to always build project and file structure in a scalable way and this is of course completely possible so actually in angular we don't have a super scalable structure there are some rules and guidelines how we can structure our components but we can do better so my idea actually in all project is inside app to just create modules for example let's say that we have website with login and feed and something else so i would create here a module login module register probably a module pagination or maybe a feed and then share some things between so if we are talking about our to-do mvc here this will be the first module of course our project will consist only from one module so actually in single module we can render the whole application because it's not that big but the idea is that we can use different modules for different pages like for different features this is why here i want to create new folder to those and this will be our new feature or our new module and here let's create new module and name it todos module.ts and let's jump inside and if you don't know how to create our new module we can always open on the right app module and check it of course we won't have everything like here but it will be similar so first of all here we want to export class and we name it to do's module and just to remind you we always want to have this postfix as an entity so we're here in modules and actually i named the file not correctly it is to do's module so module is our entity and to do's is the name so when we're writing here class we make here like camel case name with entity and the name the next thing that we need to do here is of course add our decorator ng module and as you can see i have really nice autocomplete of my editor and if you don't have something like this you either need another editor for example something popular like vs code or you need to install some plugin for support of typescript and then you have all this nice stuff like type checking auto imports and so on and this is super important when you are writing typescript or angular so as you can see here i have a nice imports so here we can define in ng module what we have for now we don't have anything so i will just create an empty declarations and an empty imports and here we will define everything that we need for our module so our module is ready but now we should not forget to register it inside app so the point is that everything is started with app module ts and this is our main module but if we won't bind our to-do's module here it just won't be binded and won't be read by angular so what we want to do here we need here inputs and we want here to write to those module and as you can see here i also got a nice import but here is the small problem as you can see here is always a relative path and we don't want to use relative path why not because it is difficult to copy and to understand where this file is located so we always want to use absolute path in this case it will be easier to just copy paste this line to another place and we don't care where this file is lying so actually in angular we have a lot of possibilities to use absolute path and actually one of them is completely out of the box so here as you can see we have source folder and actually because of our ts config json this source folder is already our absolute path so what we can say here is source slash app and here we have then to do's to those module and as you can see i don't get any errors from typescript and if you don't see any errors in typescript in your editor you can always look here in the console so no errors here and this is absolute path so i highly recommend you to always write absolute path for example like this starting with source and here something is not correct of course because it's not to-do's but just app slash app and here we have then source app and app routing so this is much better now our to-do module is successfully binded to our app module and now the question is how we will create and structure our components what we can do here is simply create an additional folder and name it components and all our to-do's components will live here and what i want to do here is create our first component and let's name it to those components so for this i will create additional folder so the point is that inside every component we will have several files and to make our structure really nice and reusable we want to put everything inside specific folder this is why component to dos is our root component for todos module and here i'm creating creating todos component dot ts and then todos component dot html and i'm not creating here css just because we have global css which is already imported now let's create our first component so actually here i will just write for example h3 and here inside will be todos so just plain simple html now let's jump into s file and register here our component so for this we have our class to-do's component and again we have here our name to-do's this is the name of component and here is a postfix which is our entity now here we need a creator component and it is of course auto imported and inside we need to set a selector so what is selector this is our todos element and the point is that normally we will just write here to do's which is actually not the best approach what we want here to write is app dash to dos why is that because we want to have some prefix for all our components and then if we want to write something inside our html here we're writing app to do's and we understand okay this is the component of our application but if we are using some library normally you will have something like mla to do for example and you understand okay this is not my prefix this is some library so this is really nice to make your application more understandable so here we have our component app to do so here is prefix then dash and then the name of the component and the second what we need is our template url this is our html file so here we are saying to do's component html and our basic component is already there now we need to register it inside our module so let's jump back inside our todos module and here inside declarations we want to write to those component and as you can see i always get this relative path because my editor thinks that here absolute path is not needed because it's not that deep inside but of course i highly recommend you to write source app and here we have to do's components and then the full absolute path so we successfully added to our declarations our component and now the question is how we can render it the main problem is that if we're jumping inside our project that we have here just hello to those mbc so normally inside our app component in html we have a router outlet so we can write here router outlet and close it here so slash router outlet and this is the place where angular router will render our page so if we will go inside a protein module as you can see here are our routes so we don't have any this is why this is empty array and we're registering here route modules for root this is how we normally register global clouds inside angular so this is approaching module and we're using it inside a module here so this is import approaching module and this is how we register routes and this is all fine and normally people would just write here in a new route for our to-do's for example on slash route we're rendering this component and actually it's not the best approach first of all it won't work with lazy loading secondly we want to isolate everything and routing also inside our module to do which means we somehow want here to define all routing that we need and just bind this to this module like we already did in this case if we are removing to this module then our routing will always be automatically removed because this is inside to those folder so what we want to do here is define new routes so here is routes and here we are setting that this is of type routes and this is important because in this case we're getting nice understandable autocomplete so here as you can see i have path and i'm getting directly autocomplete just because here i wrote that this is routes so our path will be just an empty stream because we want to render it in the home page and here is our component and here it will be to those component so as you can see this is really nice because we are using the studios component only isolated inside our to-do's module and now the next step is to use our routes and for this inside imports we can write router module dot and here will be for child and this is important part as you saw here inside a routine module here we have router module for root so this is for root which means this we are only using once inside our app module and as you can see here we don't define any routes because we want to define all routes as children inside our other modules for example here we are defining route with this component and here we're using router module for child and here inside we are passing the array of routes which are belonging to to this module now let's check if it's working when we reload the page as you can see here is our to-do's and we don't have any errors so everything is working the question is how so first of all we have here app module and app component and here we have our router outlet so normally in this outlet the page which is inside active route now will be rendered so here inside approaching we don't have anything in the routes but inside a module we binded our todos module this means that inside to this module we're defining our routes and this is our route and inside here for path slash we will render inside our todos component and our to those component it's just a plain angular component we select app to do's and this content so as you can see our first module and first component is already rendered and it is done in a really scalable way because we're doing it like completely isolated modules and we can scale it indefinitely now let's start thinking about what components do we want to create so here in the example as you can see on the right we have at least several of them so first of all we have something like header where inside we have our input and when we are typing something and hitting enter then new item appears here and here is the main part where our list is rendered we can select here something or remove and here we have a component with footer where we have information regarding our tasks and also filters this is what we want to implement this is why i highly recommend to create these three components like header main and footer so first of all let's jump and create inside to those components new component header so here is our header and let's create inside headercomponent.html and headercomponent.ts now inside headercomponent let's write some basic markup so what we want here is first of all header with class header now let's close our header and inside we will just have a single input so here will be input with class and here will be new to do and here is our placeholder so our placeholder is what needs to be done and actually if you don't know where to take this html you can always jump in one of the examples inspect the elements open dom elements and here check all these classes as you can see here is our header then inside we have an input and actually h1 tag also so here i will close our input and first of all write here h1 with just to do's inside also we want to add an autofocus for our input because here when we're just reloading the page as you can see i am already in focus for this field and this is just out of focus with camel case and we're getting this feature out of the box so let's check this out we're reloading the page as you can see nothing is there because we didn't bind our header and we didn't create our ts file yet so first of all i want to copy paste to those component ts because it will look exactly the same so here i copy paste it inside header our app to do's and here i want to name it app to do's header so here inside name we have an app which is the prefix of our application then we have a name of the module and then the name of the component in this case we always know from what module this component is and now here the template url will be header component html and our class is header component now we also need to register it inside our module so let's jump inside to this module and here in declarations we need to add our header component as you can see here it is again please write always absolute pass i won't change it everywhere now but you got my point so we successfully registered inside declarations our header component and we need then to render it so let's jump inside components to do's to those component html and here we don't need this h3 anymore but we need a markup so here let's write div class to do app let's close our div and inside first we will have only header but of course we will create main and footer later so here we have app to do's and here is header and let's close app to do's header and now let's check if it's working at all as you can see in browser we're getting here already correct styling here is our title and here is our input and as you can see out of the box we are getting autofocus the only thing that is bothering me is this title that we don't need so let's jump inside our app component html and here we don't need h1 tag but just router outlet and this is looking exactly like in the example now we somehow need to read a value from this input so when we are typing something we want when we're hitting enter to get a value and there are several ways to do this first of all we can use ng model which is two-way data binding which means we're changing our input and we're changing at this time some property inside our ts file but i really like to have not two way data binding but one way because it is easier to understand and easier to debug and for this we can simply jump back inside our header html and here on our input we want to add a value so here we are writing value in square brackets and here will be some property in our case for example text and after a value we also want an event so here we can write that we have key up event and here we have a function change text and we want to pass inside dollar event so the idea is that we have single flow of data so this is the value and we are just reading this value from this property and we also have an event key up and this change text is changing this value so now let's create this change text function so here inside our header component we can create change text and we're getting here event and as you can see by default we are getting it as a nanny because we didn't specify the types and this is extremely important if you want to write save code this is why here i am saying that we are getting event and here then inside we are working not with just any but with event but here is an important point here i can write console log event target value and actually it will work but we will get a typescript error when we check in browser actually it is working so we can type something and we are getting the value so we are getting this typescript error because we don't have a value inside our target and as you can see here inside target we have data type event target and actually event and event target are really generic classes of the highest hierarchy which actually means that we need to say here that we are working with input in other case typescript doesn't know that this is an input this is why here we can create for example target and we are saying here that we have event dot target as and here html input element so we are explicitly saying that our target is not just event target but html input element and in this case inside console.log we can write target.value and then as you can see it is working and we don't have any problems the next thing is that inside our html we created this value text but we didn't create it inside our ts file so let's create here variable text and we know that this is string and by default it will be an empty string so let's reload the page as you can see here we don't see anything because it is empty now i am typing something and as you can see in the console we are getting the value so actually every time when we change this input we are setting here something inside the text so we need to write here this text equals target dot value and now it is saved and we can use it also when we are submitting the form so here we can submit our form only when we are hitting enter and in angular there is a really easy solution for that so we need to jump inside our html and here we want to say keyab dot enter and in this case our key up will react only for enter and here we can say add to do and we don't need to pass anything inside now let's create our new function add to do and here i will write void and just to remind you we're using voids everywhere where we're not returning something back so here we can also say that we're returning back void and actually if you have some typescript questions i already made a full course on that here on youtube so i will link it here on the top also so here in add to do now we can write console log add to do and here we're just console logging this text so the idea is that we are changing it here and then at some point we are submitting our form and here we want to read this text so let's check we're typing something here and now i'm hitting enter and as you can see we're getting in console add to do and here is our console log so as you can see we are getting access to this text and everything is working correctly the next question is how we will store our data in the project at all so if we check in the example you can see that we don't have that many data we have an active filter here on the bottom and we have a list of elements here where we're rendering them so actually we can do it without service and just store all data in the parent component but with service it will be easier to make and to scale this is why i highly recommend if you are storing some data always store them inside service and not inside component so let's create our service for to-do's which will work fully with everything that we need about to those data so for this inside app to do we're creating new folder services and inside we will create new service to those service ts and actually my recommended naming for all services is when you don't know what the service will do or this will be just a general service for the module then we are naming it with the name of our module so to do service ts now here we first of all need to say that this service is injectable this is why we're writing here injectable with round brackets round brackets are important and people are normally forget them and here is our export class to do's service and as always in the name we have a postfix of our entity and our entity is service so first of all here we need to understand in what structure we will store our data and i highly recommend you to always use observables or behavioral subjects because angular is really working nicely with streams with the rigs js this is why we need to use them fully this is why here i want to create to-do's which will be just a behavioral subject so here i want to say new behavior subject and here inside we are passing an empty array so what is the idea of behavior subject this is just something some entity where inside we can set some default value and here to those is a behavior subject which means we can change it and we can subscribe for it like for observable so actually it's not some plain data it is the stream and with streams is easier to work inside angular because we can get the data from the stream when we are changing them and modify them easily but here is the important moment we didn't define any data type here so we are just saying that here is empty array and we can throw inside whatever this is of course bad and normally we want to create interfaces for all entities inside our application and actually in our application we have only a single entity and this is our to-do so the question is what our to-do needs to have inside first of all is of course the name so here is the name of our to-do secondly is the state so is our to-do checked or unchecked and the third property is of course an id because in this case we can easily search for specific to do in our list this is why i want to create new interface and this is interface which is related only for our to-do's module this is why here we're creating types folder and inside we will have our to-do interface.ts so here i want to export interface and here will be our interface to do interface so don't forget postfix interface and as i said here we have id this is a string we have here text also string and we have here for example is completed so actually we can create here some state like a string for example active or inactive but we only have two possible states this is why here we can say is completed and here it will be boolean so by default it will be false and then when we're selecting it it will be true now we can provide this interface inside our behavioral subject so let's jump back into the service and here in tags we can write to do interface array so in this case we are saying that our behavior subject can have inside only an array of to-do's and as you can see now it is completely clear what type of data we have inside our to-do's now we can everywhere use our to-do service and use this behavioral subject to do's to store and update our list of to-do's what we need to do now is create a to-do method so we can add a to-do from every place of our application so actually the idea is that we're jumping in header component ts and here we have add to do but we don't want to implement add enough to do inside header component because header component should not know anything about creating the to-do so what we want to do here is just call our service and for this we first of all need to inject it and secondly call it here so here we need a constructor so we can inject it and inside constructor we need a private variable and it will be to do service that we just created and here it will be to do service so we need to import it here on the top and now here we can use this to do and we don't have any method here but as you can see we have access to our behavioral subject which means we can read and update its value so here what we want to do is just call add to do we will create it in a second and we want to pass inside this dot text so this is the only property that we need to provide from our header now let's jump back inside our to-do service and create here a public method had to do so now we know that as an argument we're getting here our text and it is string and back we're getting void because we just want to modify our to-do's list and actually as you see it is a behavioral subject it's not just an array which means we can't directly just push elements there so we need to do it a little bit differently but first of all i want here to create a new to-do so what i want to write here is new to doom of type to-do interface and this is really nice because in this case we already know what fields we need to provide inside so here we are getting an error that our object is missing the following properties id text and this completed and actually if i will just remove our to-do interface then we don't get any help this is why it is really nice everywhere to specify our interfaces and our to-do interface is really shareable entity between the whole application so here we want first of all text secondly is completed by default is false and third is our id and actually id can be tricky but we can really do easy just by using math random and i highly recommend you to use math random like this to get an id so we can simply say here meth random and this is just a flawed number and here we can write tostring this is how it looks like and then just take first 16 symbols and this is really nice and easy way to get some stringified id this is why here i will write math random to string and this will be our new to do and of course if we have some backend normally we just make an api call to the backend and it delivers for us an id that is generated on backend side we don't have here an api this is why we need to generate ids on frontend and actually if we will use such code several times then it makes sense to create some global functions something like generate unique id so here is our new to do now we need to push them in the list of to-do's and what we can do for this is create updated to-do's and this is just a plain array and here what i want to do is read all values from our to-do's so for this we can write these to do's get value and this will return plain data from our behavioral subject in our case it will be the array of to-do's and as you can see here i used spread because we want to merge all these values from the array with our new to-do and our new to do is going to the end and this is how we update our to-do's and as you can see here we directly get that we are getting back to do interface array because we are merging value from todos allowing you to do now we just need to update our behavioral subject and for this we have a function next and inside we are providing a new value and our new value is our update to do's so this is exactly the code what we need to add it to do to our list of to-do's now let's check if this code is doing something so i want to jump back to our header component and inside constructor subscribe to this to do service and here is to dos and actually behavioral subject can work as an observable which means we can subscribe for its value this is why here i am writing subscribe and here we are getting our to-do's and i just want to console.log here how to do in this case every time when we change our stream we will get here a value and as you can see here we are getting directly back to do interface array this is exactly what we want so here we subscribed to changes to our stream of to-do's so let's reload the page and see if it's working so obviously not we have some errors as you can see we didn't provide our to-do service inside our module so we need to register our to-do service inside our to-do's module so for this i will jump into those module ts and here we need to create new property which is called providers and we must provide our to-do service inside this array of providers now when we reload the page as you can see we don't have any errors and as you can see in the console we already got our first console log and this is our stream from header and as you can see by default we don't have any to-do's now i'm creating you to do and as you can see after i'm hitting enter we directly got an update in our stream and as you can see here we have our first element here we have our unique id is completed false and our text so this means that everything is working and our add to the function is implemented correctly so now we can just with single line like this everywhere in our application use to do service to add a to do and what is really important our header doesn't know anything about implementation of to the service or ad to do we simply call here add to do and this is it so let's remove console log and we don't need this subscription because it was just for testing and actually as you can see here our header is completely ready so on reload we have here focus then when we type something we are updating our array the only problem that i can see here that we don't remove the value from input after we're hitting enter and we can easily fix it just by jumping in our add to do and after we successfully edit the element we want to reset this text so here we can assign inside empty string now let's reload the page type something and when i'm hitting enter as you can see our input is empty the next step is to render all our elements and as i already said we need to create additional component for this this is main component where inside we will render our entries so for this let's jump in our components so here we have only header and to-do's and actually to-do's is just a parent for everything so inside after header we want to write app to-do's and here will be not head but for example main and now we must create this new component here so i will create main folder and inside main component dot ts and main component.html now let's just write inside main in html and create our first component so we need here component and here inside we want to provide our selector so our selector is app to do's main and now we have template url and this will be main component html and here is our class of course with export so here is main component and our component is actually ready now we just need to add it inside our module so i am jumping to to this module and here inside declarations we must write main component and as you can see i got as always auto import on the top so now when i reload the page as you can see we don't have any errors but we don't see our main it may happen that angular didn't get that we created new component it can happen really often this is why the easiest way is just to restart web server if you don't know if you made an error or not in this case you can be sure that it's not the problem of angular and as you can see here we successfully got our android component which means actually it was not a bug but angular just can't get somehow the changes that we did to the files especially when we create a bunch of new components so as you can see our main is there and we can render some content inside for this let's jump back inside main component ts and think about our data and for this we need to look in the example and actually the point is that angular together with the risk.js gives us a nice and strong opportunity how we're writing the code with streams but the main problem is that it is not easy and in other frameworks we're writing it differently this is why it is really difficult to adjust how we're writing code together with angular and interior rigs so let's think about our application here what do we want to show here inside main section as you can see here we are rendering elements and they are depending on the active filter so actually we can say that we say for example filter inside our service like a value so when we are clicking active our filter value is active inside service but then we somehow need to filter all our data with this filter so normally what people are doing they are subscribing to our to-do's for example something like to-do subscribe and then we're getting here to do's and we have them like local variable and then we think about some usage with other properties for example here we want to filter our to-do's then we are right into those filter and we're filtering them by this active filter and of course this is completely possible and this is how people are writing in other frameworks but it doesn't make any sense to write code like this inside angular because we have rxjs and it is much easier to work with streams this is why we want to really make it correctly and build even this small to-do application using streams so what do we need to do first of all as i already said we need to store somewhere active filter so this filter on the bottom by default it is all and then when we're hitting here a button we change our filter so i really want to jump back in our service here and create a new behavior subject and again as you see i am operating with rixjs streams i'm not operating with values because rxjs is really super powerful with streams so what we want here is filter and it will be behavior subject and here what we want to do is create an enum and actually yes we can simply store here a string like all active or completed but we have in typescript enums and this is really a nice place for anem so what i want to do here is write filter enum and here is the type of possible values and here is the default value and filter enum dot for example all will be our default value now let's create this enum i highly recommend you to store all enums together with types so what i want to do here is create filter enum dot ts inside to those slash types and here we can create new enum and name it filter enum and here is the object with three possible values this is all active and completed so we're just storing here three strings but this is really nice because we have a data type as a filter in them and all these values this is why active is active and of course completed is completed so as you can see this is just a plain typescript enum and inside we have three strings but now when we are jumping in our service and importing here our filter enum as you can see first of all we are using filter enum as data type this is why we can't really provide a wrong value inside our filter because we said only this enum is valid and now here is the default value filter enum all and as you can see this is just a string all so here is our filter and how we are storing it the point is that in our main component we want to get only visible to those so they are visible depending on the list of our to-do's and the active filter and we can really easily do it with rxgs because we have two streams so what we want to do is use these two streams inside our main component this is why here inside main component i want to create for example observable visible to those and this will be a stream of observable and here inside we will have array of to-do's this is why it will be to do interface and by default it doesn't have any value because this is an observable and we will assign it directly in our constructor the most important part that we always specified that here we have a data type to do interface array so now we can create our constructor and inside we need our to-do service so here is our to-do service and here is to-do's service actually not to do but to-do's with ass and now inside our constructor we can combine two streams so here we have access inside this to do service to to do's stream actually behavioral subject but this is for us here also a stream and filter is a stream so we want to combine these two values and depending on the values that we are getting from them we can calculate something in this case we can use here this visible to do's this is our result and here we can use combine latest and if you don't know what combined latest from rxjs is doing it combines streams in our case we can combine two streams this to do service and here will be our to-do's and this to do service filter so here we are combining two streams and we're getting some value back and of course we don't want just to get two streams back we want here to get back an array of to-do's as an observable this is why here i am writing pipe and inside it will be map and if you are asking why we have here pipe because this is an architecture of a rigged jazz so the idea is that pipe is simply a list of functions that we want to call on our stream so actually combine latest gives us a combination of stream and then we want to call several functions on it and the first function here will be map this is why we always write after dot pipe and we're doing something inside so here inside map we directly get two values inside an array first of all the array of our to-do's and secondly is a filter and if we open the documentation as you can see combined latest here is the most important line when any observable emits a value emit the last emitted value from each which means when for example we are getting you to do we are getting here inside map and we are getting these to do's with a new to-do and our active filter so here inside map we have a result which is an array this is why here i will destructure it directly to get to those and our filter and we need to specify here that we are getting back to do interface this is an array and here we have our filter this is our filter enum and now we should not miss our brackets this is why inside here inside map i want to have some logic but first of all here i want to console log first of all it will be combine so we can see that this is our combine and inside we have our to do's and filter and after all our calculations that we will get in a second we want to return our visible to those and i will simply return here empty array so it won't break as you can see this code already works because of course we didn't do some calculations but we returned here an array this is why here visible to do's is valid this is an array which is just empty but now you probably are thinking this code is not looking really easy and it is quite complex and we are writing a lot of brackets and so on yes but this is a way how you must work with angular only by using eric's chess and here are several benefits why this is good first of all we don't write here subscribe and as you can see because we don't write here subscribe we have only this value and we will use it directly inside our html just by using async so here inside our html we can write now for example brackets then we have our visible to-do's and we're writing a thing and this is all we don't need any subscribe and then glob will do everything for us and here i want also to write a json because we're getting back in ray secondly here we will get changes every time when something will happen for example when our to do changes or our filter change then we're getting here directly new value because here we have some calculation if you will try to write it not in a rigious way you need really to have here to subscribe and then somehow synchronize and calculate your value when some of this value is changing this is really consuming and not productive and not angular way so let's check if it's working at all so we're reloading the page and everything is broken as you can see the pipe json can't be found this is happening because we must provide inside our todos module common module from angular as you can see we didn't provide it here in inwards and actually we need to inject it every time when we're creating new module so here inside imports we need common module and this is from angular and i just import it so as you can see this is from angular common and a lot of stuff like router stuff or these nges and so on it all will work or this pipe also just because of this module now as you can see in browser we don't have any errors and here is our array that we're getting directly inside our html so as you can see when we have a stream we can directly write it like this with async and here of course i'm using json just so we have a pretty json inside our html but the main point is that we don't need any subscribers unsubscribers and so on because we simply have here an observable also when i am typing something here in our header and i'm hitting enter as you can see we're getting directly inside combine and here you can see our new element and this is exactly what we wanted we wanted to react on the changes in our two streams from our service and somehow get a new value so this is exactly the main difference from other frameworks in angular we're using heavily streams from riggs.js and we're not just subscribing to these streams but we directly combine them or change them or map them inside our components to get new values and we will use this logic a lot just because angular for us unsubscribes the streams when we're using a sync pipe now we just need to write here our logic with to do's and filter so first of all here we have a nif our filter equals and here will be our filter enum dot for example active so we want here to return only active to do's which means is completed should be false there this is why here i directly return our to-do's and here i am using filter and we want to filter inside all elements where is completed is false this is why i am putting here bank and this code will directly inside visible to do's write filtered elements the next logic is here if else our filter equals completed this is by filter enum dot completed and here we want exactly the same logic so i'm copying this filter but without bank so here to do is completed so here we're getting only completed to do's and if these two cases are not there so they are false we want to directly return all our to-do's so we just write here return to do's let's reload the page and check if it's working so by default this is an empty array actually this is in our html and now i am typing something and hitting enter as you can see directly here inside our html we have access to our to-do because we are here in this return because our filter by default is all it's not active and it's not completed and as you can see directly when i just type something and add an item in our service we react through our combined stream this stream is changed then we're calculating this value and we're rendering it directly with single line inside html and this is exactly how we want to write our code inside angular now let's write a markup for our visible to-do's so let's jump in html remove everything and create here all with class and here will be to-do list so inside this rule we want to render the list of our to-do's so here we need to close our ul and inside render the list so here we will have lee and probably later we must move all this content to additional component because we have quite a lot of logic here first of all here we can check uncheck the element we have remove but also we have in line editing so when i'm double clicking here as you can see we have inline input and we can change the value so it is quite a lot of logic and they don't want to write it directly inside our main component but for now just to see the list we can render just a bunch of li instead this is why here we have lee and here we need an ng for loop and we want to loop through our observable this is why here we will have led to do off and here will be visible to do a sync now inside we can just render our to-do dot text and let's check what we have so here in browser as you can see we don't have anything now i'm just creating new element and here it is so all our new elements are directly rendered inside our main content now as i already said i want to create new element for example component to do and move all logic with rendering there this is why here i want to create new component and let's call it to do and inside we need to do component html and here will be to do component ts and the question is how we will name it first of all i don't want to write it directly like i did before this is why i will copy all declarations from our to-do's component just to avoid typing and here we have not to do's component but to do the template url is to do component html and the name will be then app then to do's this is the name of our module and the component is to do now we need to bind our component inside module so here inside declarations we need to add our to-do component actually not to do's but to do component now we have the correct import as you can see here the next question is what we will pass inside so inside our components main here we have lee actually we don't need here lee anymore but we can render here app here we have to do's and here to do element and let's close it here so it is app to do's dash to do and now inside we don't need to render something like this because we will render all markup inside our element and this is why inside here we can remove everything but we want to pass some data and in our case we want to pass our to-do so here we are looping through the list of to-do's and here inside every element we will pass as an input the whole to-do in this case we have the whole information and our to-do is actually stateless and we will simply render the to-do or emit some events for outside now we need to define this to those input so we need to jump in our to-do component yes and here we're saying that we have an input if you don't know input is the way to pass some data to our children in our case we want to pass our to-do but here is the interesting thing that not a lot of people are doing we can use here aliases so normally people are writing something like this input to do and we have local property this to do the main point is here that then all our properties which are local are just this dot full or this dot bar but also our input is this dot to do and in this case we don't see any difference between our input and any local properties and this is not what i want because for me it is easier to work with inputs like for example in props if you know something about react the main idea is that props are read only in react view and obviously in angular it will also make sense to treat them like redundant properties this is why actually i want to mark them with to do props so here i can write something like this and i'm saying here that this is to do interface so what is happening here we defined that we have an input to do which means outside we are using it like to do but inside we have local alias to do props so there is no such property like this dot to do but instead this dot to do props and when i see such local variable i know that this is coming from the input and i will never mutate it now let's render our to-do inside so for this inside html we can simply create for example li element and inside this li we want to render not to do but to do props dot and here will be text and in this case we directly see okay this is coming from the input now let's reload the page and check if it's working so i'm typing something and now we're rendering this information but not inside main but inside our to-do component which means we created additional component and in this component through our input we are passing each to do now let's finish our main component so actually when we check in the example here you can see that we have this element on the left which is actually toggle all but the point is when we inspect this element here actually it is situated inside main so you can see here is main part and we have this toggle all with top and left actually because of this top it looks like this element is inside header but actually it is inside main which means we need to implement the same logic inside our main with toggle all and also when we don't have any elements here so we will remove everything as you can see we don't see main and we don't see footer which means we need to create additional class to hide our content so let's jump back in our main and here we want to add one more element so what i want here to do is create section with class main and let's close this section at the end so what we want now to do with this section is to add here in g class and the interesting part is that in ng class we want to apply class hidden here i will write just false for now but later we will change this to variable so the idea is that hidden should be true when we don't have something to render which means if we don't have any visible to do's this means that hidden should be true which means we must create this property and actually eric streams can help us with this so let's jump directly inside our main component and we want in our constructor to create one more property and actually here we can create it and name no to do class and here is the observable of boolean which means we're getting here true or false and depending of it is true or false we are attaching here this hidden class so what i want to do here inside our constructor is to write this no to do class equals and here we need to use this to do service and here we will have our to-do's so what we want to check we want back from these to do's to get either false or true and it is true when we have to do's and it is false when we don't have to lose so for this we can use here pipe and map like we already did previously and inside map we are getting back our to-do's and what we want here is to check to do's length equals zero y is equal to zero because here is no to those class which means we want to get this class in true only when we don't have any to-do's and this is exactly what we have so we created new observable and we are watching on our stream to-do's and here we have pipe with map and actually map transforms our stream and here we have access to all our to-do's that we have and inside we can check ok we're returning here our no to those class when to this length equals zero which means here we want to write inside html instead of false now no to those class and here is a sync and let's check how it looks like so we're loading the page we don't have any errors and as you can see here our main is not rendered now we're typing something and here is our main and let's check now in inspector our element as you can see here we have our main and then to-do list so actually here is to-do list and here is main section this is this now the point is when i reload the page as you can see here is our main hidden which means this container is hidden because our no to those class was resolved and this is true this is why we attached here hidden class as you can see with using rxjs our html is really easy and our code in tis are just a bunch of streams the next point that we want to implement is this toggler on the left and actually this is an input with the label and we need to render them inside our section so here we have an input and here we have id toggle all and here also will be class toggle all and type will be checkbox now after this we want to just close it and we also have a label so here will be label 4 toggle all and this is exactly why we have here id so this label will focus the id and here we want to close our label and here we want to right inside mark all as completed and this is it so we have a label and an input let's reload the page and check if it's working so we're typing something we see here our element here on the left just because our main section was rendered the next point is that we want to highlight it as checked when all our to-do's are checked so here in the example you can see when we're clicking this is checked so this is gray because all our items are completed and we want exactly the same approach and we of course want to use streams here so we have an input and here is type checkbox and we want here to attach checked so it should be checked when our stream will be resolved and here i want to create new stream and name it for example is all to dos selected and here is of course dollar because this is a stream and here i am writing a thing so exactly like previously we will create new observable and we will resolve it here so actually this input will be checked when all our to-do's have status is completed now i will just copy it and create in our ts file new observable so we know that this is observable of boolean because here we have is which means this is a boolean now here inside our constructor we can create this is all to do selected and exactly like previously we can use here this to do service to-do's because we want to access our to-do's and the point is that here we want to check that every element inside our array has this property is completed inside true this is why here i am using pipe map again and here inside map i am getting access to todos and here we can use plain javascript and just try to do's every and here inside every we're getting access to each element so this is to do and here we can say to do dot is completed what does this code do so here we have a stream for to-do's and here we have a map so we transform our stream to some other property and as you can see here we have access to our to-do's which is an array now what we're returning here is this construction so what we're doing here we're using using todos every and every accepts a function with a predicate which means here we will get back true if every element of this array returns true so here we are checking for every element and this is to do that to do is completed is true which means if every element has property is completed in true then this stream is all to do selected will be true so let's check if it's working so here when i will type something as you can see this is gray and we don't have any possibility to mark it as completed but here is the solution just to test that our code is working we can jump back in our service here and here we have this new to do and we are creating you to do with is completed false we can change it to the true and then by default this element should be grayed out this is why here i am reloading the page i am typing something and as you can see now it is not grayish but this is more about black so we can inspect this element and as you can see here we have this checkbox and this is checked so everything is working as we expected now what we want to do is implement clicking on this element as you can see actually checking and unchecking is working just because this is plain html but this is not enough for us here we want to actually change the status this is why here on our input we can add new event and this is change event and here toggle all to-do's and inside we are passing our dollar event so here we need to create a new function toggle all to do's which will mark all to do's as is selected or is selected false so let's create this function now inside main for example here after our constructor we will create toggle all to do's and inside we're getting our event this is why here is event of type event and here we're returning void so what we want to do here is to get our target because we want to read event dot target dot checked and we can't do it because actually target should be html input element so here i will create our target of event.target and say that this is html input element now here we can use this target.checked and what we want to do we want to pass this information inside our service because only our service is working with our data this is why here i am writing this to the service and we need to create a new function for example toggle all and here we are passing target dot checked so we are passing here either that our checkbox is checked or not checked and here we are calling toggle all function now let's create in our service this toggle all function so here we know that toggle all accepts only one argument so it will be is completed so actually is completed is a boolean and it either true or false and here we have also void because we don't want to return anything now what we want to do is loop through all our to-do's and change them all either on false or untrue for this we can use a simple map so here we can create a property updated to-do's and here we want to loop through these to do's and here will be get value so we're getting just plain array and i want to map through every element and here i'm getting access to the to do now inside i want to return the same to do but override is completed property this is why here will be returned and here we can spread our to-do so we're just getting all properties from this object and we are overwriting is completed fully so this is completed this is what we are getting from our function so let's also console log it here so we can check that this is correct and here as you can see this is our updated to-do's i won't write them directly in these to-do's so let's check first if it is working at all so here is our updated to-do's and it should just loop through our these to-do's and update each value which is completed that we passed here so let's reload the page check that we have any errors we don't so now i will just create new element here and of course by default it is also toggled we don't want this this is why by default here i will change is completed to false now let's reload the page again and here i'm creating something this is gray now i'm clicking here and this is what we have so is completed is true because our input is checked you can see this here and now this is the list of updated to-do's as you can see we have only single element and here is completed is true but actually by default our new to-do was false and because here we map through and set is complete to true this is true so our updated to-do's is there and we just need to override it in these to-do's and here we're just making next and we're passing here our updated to-do's list in this case we're just updating to-do's and then inside our main here we have our stream for is all to do selected and here this to-do's will be changed and then we calculate our property again this is why we're loading the page we're just typing something and as you can see this is gray here now i'm clicking here and this is not gray anymore because actually we changed all our to-do's 2 is completed but we actually can't really see it this is why we can jump directly inside single to-do and here at for example span and inside this pan i just want to see for debugging to do props dot is completed let's reload the page and here i am typing something you can see that this element is false now i am clicking here and this element is true i am clicking again and this is false which means everything is correct and our function really changes all our to-do's to false or true now before we will continue to implement a single to-do i want to implement footer component so let's check this out here is our example this is our footer so here we have zero items left so this item is changing depending of the items that we have in progress also here we have three filters all active and completed and we can switch between them and the only thing that we're changing is active filter and of course the list of items so here all shows all items then active only active and completed only completed so now let's implement our footer component for this i will jump into those components and create here new folder footer and inside footercomponent.ts and footercomponent.html and now inside let's just write footer so we can check if it's working and here is our footer component i don't want to write it this is why i will copy paste it for example from header so actually i want to copy this class and component so i won't write it again so first of all we need to auto input our component and this will be app to do's footer now here we need template url footer and the name of our class will be footer component so our component is ready but we need to register it inside our module so let's jump inside to this module and here inside declarations i will add footer component and let's save this out and actually it should work let's check actually here nothing is rendered because we forgot to render footer inside our layout so actually here we can jump in components to do's in our layout for todos and here i will copy our main and right here app to those and here we will have footer and now i need to close our footer component so as you can see now on the bottom we have this footer part and actually between we have this main and then footer so actually we have footer always and we also need to write some logic to hide it now let's start with hiding this footer so for this let's jump in our footer and here we want instead of this word right footer and here will be our class footer and here we want ng class like we did already in main so here we want a new class and this class will be hidden and we want to attach it if we have no to those class async and actually we already implemented this part inside main so we can copy paste it obviously we can move it for example in service but i don't see really that this is that shareable now here let's close our footer and right inside for example footer so now here we need in our ts to implement this property and i don't want to type a lot this is why i am jumping inside main and here we want to copy paste this no to do class and for this we need to create here constructor and we want to inject here private to do service this is our service of to do service let's close this now and inside i will paste this lines that i copied but first of all here is to do's service and not to do secondly we need to create this property so now to those class and actually the naming was not correct there it should be no to those class but it doesn't make any difference because this is just a local variable so this is an observable of boolean here is our property and now it's not read anymore but we also need to import map as you can see now we don't have any errors so let's check if it's working so we created this property this is our observable for todos and here we're checking that out to do's length equals zero and we're using this property here to add hidden class when this observable isn't true so let's reload the page as you can see we always see footer and this is not correct actually here in console i can see that there is an error and we didn't name our property correctly so as you can see here typescript says that the property is known to do's class not no to-do class this is why here in our html we need to rename this property and then it should be compiled now as you can see we don't get any errors and let's reload the page and open our console so there are no errors in the console and we don't see our footer now we're typing something and adding an item and here now we're seeing our footer so our logic is working and now we can create inside footer on the left this counter here so we have one item left so actually first of all we have here item and items so this is singular and plural and here of course a counter so what i want to do i want to create two new observables one for the string and secondly for a counter so this is why i will jump in ts file and create here two new observables first of all here i want this active count and this will be the count of our active to-do's so here we can use for this this to do service and here as always we have to do's then pipe and here we want to map our value and inside value we are getting to do's and we want to get here only to-do's that are active and we already wrote this code inside our combined latest in rix chess so here will be to-do's then filter and here we have access for each to do and we're checking that to-do is completed is false and after this we can simply say lens so the idea is here that this will be the result so we're filtering our array with is completed false and then we're just using dot length and we are passing this inside of this active count so we need to create now this observable and it will be observable of type number because here inside we're using length and the second thing that we need is our label as you can see this label here can be singular or plural and actually we can also create an observable and store our label there for this we can say this and here for example items left text so here we have a text regarding how many items we have left what we want to do here is to use our observable this active count and actually it doesn't mean that we always need to use only this to do service we created here a new observable and we can map it also so for this i will write here this active count and we know that this is the length so this is the number and here i want to use pipe and map inside our number so actually here we have active count and we know that this is a number so here we can write a string that we're getting back so here will be item because it is singular then we have here logic so active count not equal 1 because it must be more than one item then we have an s here then here we can write a ternary operator with s or empty string and here at the end space left and yes i understand that writing a ternary operator inside the string is considered a bad practice but here we have only a single line and i can't say that this is really that not readable but of course you can create here several lines and move this ternary operator logic to some additional property so here we created our item's left text and we need to register our property so here it will be observable of string so we successfully created two observables and we can just render them inside our html so let's jump inside footer component html remove here footer board and write some markup so here we will have to do count this is our container so now inside we want first to render an active count so here will be strong because it should be bold and we don't have a class for this so here i'm closing strong and inside i have this active count with dollar and of course a sync because this is an observable and after this we want to render our text so here we have items left text and here is a sync let's save this and check if it's working so we're loading the page we don't see footer now we're adding something and here we see one item left now we create one more item and we see here two items left as you can see rigs.js is really super powerful we can create new properties based on some logic or some streams and everything is updated automagically and we don't need to write some subscribers or additional logic the next thing that we need to build is our filters so as you can see here in the example we have active all and completed so we can just render them inside markup and of course we can render them for example as an array with loop but i don't want to make it too complex this is why i will simply render three elements so let's jump here inside our markup and after our span we can create ul with class filters and here will be our filters that we can take from enum because we already created an enum so what we want here is our li and inside li we will have an a so here a graph and here everywhere i will just use a slash because we want to make prevent default and then just handle a click event on this a graph and you might ask why then i am using here a graph and not some span or development because all styling is already prepared for a so here we have our graph and now we need ng class and here we will have class that this is selected as you can see here we have highlighted element when our filter is active for example in this case completed is active and this is exactly the point here we want to attach selected and here i will just write for now true because we don't have any logic or any property to check that this filter is selected so after ng class here i need to close our a after ng class we have also click event so here on click we want to call some functions so we want to call for example change filter and inside we will pass two things first of all is event and secondly we want to pass here filter enum dot all and at this point you might ask ok why we are passing here this event because actually we are just saying here filter in them all and this is the value from our filter inum and this is enough for us yes you are completely right but the point is that we want to make event prevent default this is why we are passing here this event now inside a we can just render text all now let's save this and actually this is a markup for our three filters so i will copy twice this li and just change it so here is our second li i will leave it like this but here will be filter enum and first of all we have here active and here the text will be also active and the last one here will be not all but completed and here filter enum dot completed but here is an important part as you can see here i wrote filter enum with small f and first of all we can't really put our enums or import them inside our html we can do it only inside ts so here on the top but the problem is that then they are available only as local property and not in the template this is why here i want to create filter enum as a local property and this property will be public for our template and here i want to assign our filter enum and actually this filter enum i will import on the top so this is how we are bringing our enums inside templates and of course we don't want to write here just strings because we want to use an now let's check if it's working so here i'm reloading the page i'm typing something and you can see our footer and our filters and we're highlighting all our filters as active because we wrote everywhere selected true and also when we're clicking we have a red message because we didn't create change filter function so first of all let's create this function here somewhere on the bottom it will be change filter and we know that we're getting here event of type event and the second will be our filter enum and here we're returning void so let's at least console.log here our change filter and here we have our filter enum actually i didn't put here a value so let's name it filter so here we have our filter and let's check if it's working so we're typing something here inside footer i am clicking on active and as you can see we have full page reload this is because i wrote here a graph and we need first of all to write here event prevent default in this case we will block the default behavior of a so here we have our footer i am clicking on active and here is our console.log change filter active so this is exactly what we wanted the next point is that here we are highlighting all our filters at once and of course it's not correct so what we want to do here is to write some logic and this logic actually should be based on the filter observable so just to remind you here inside our service so to do service we have on the top filter behavioral subject and this is where we're storing our filter so now we can use this property inside our template so what i want to do is jump back inside footer component yes and here inside constructor i can create new property for example this dot filter and actually this will be an observable and here we will write this to the service dot filter and you might say why i'm doing like this and not just using service directly in the template sure you can do this if you will make it public but this is a bad approach because we want to isolate all services and just use them inside typescript and then inside html we are using only things from our typescript file this is why i am creating here filter observable and we can create it here on the top and we know that this is observable of filter inum so now this filter is available for us directly inside our html so here we can write instead of true some logic for example here filter dollar async and here i want to write equals and here we have our filter enum dot completed and actually this code is not valid because this construction won't be parsed correctly so first of all we want to execute this async and then comparison this is why we need to write here round brackets in this case it will work correctly now i will copy paste this line and paste it here and here and we just need to change our filter in onto all and here filter enum dot active so now we are subscribing to our observable from service because this is just a reference and we're comparing it with our filter in them now let's check if it's working so here i am in browser let's make it smaller i'm typing something and as you can see only all is active because by default our filter is all and obviously when we will change our filter it will be automagically changed because this is just a stream and we are subscribing on our stream this is why what we need to do now is activate our filter change so as you can see here we have our change filter but we didn't do anything so we need some function inside service that will change our filter but of course we can write something like this dot to do service here we have access to the filter and we can use here next but this is of course bad approach because actually we want to create some public method that can change our filter and not just change our behavioral subject directly in the real application i would make this filter behavioral subject and to those behavioral subject private and just allow them through some data to make it more safe so this code is bad and what we want here is something like this to do service and here we want to create new function change filter and inside we are passing our filter or actually maybe filter name is a better naming so here will be our filter name we don't need console.log but now we need to create this change filter function inside our service let's jump to our service so to do service and here on the bottom i want to create new function change filter and here we are getting our filter name which is our filter enum and here of course we're returning void so what i want to do here is just change our filter behavioral subject so for this we are writing here next filter name so yes this is exactly the same code that we can right outside but the point is that we are wrapping it in some public method change filter so let's save this and check if it's working so i'm typing here something and you can see that all is active now i'm clicking on active tab and as you can see our filter here is changed now we're clicking on completed and our filter is changed and did you saw that we don't see any items now because we don't have any completed items so actually our code is working completely correctly we filter all these items based on the filter and our to-do's so if we will jump in our main here where we wrote it in the main component ts here we have this visible to those combined latest and this is exactly why we did that so here we have two streams to do's and filter and we just changed our filter stream this is why all this logic was recalculated this is why here when we are on all we are seeing our element because this is still active now we are jumping to complete it our filter was changed and we don't have any elements to render so we successfully implemented our footer part and as you can see in our component we just have a bunch of observables from some streams from our service and we're just mapping them to the values that we need and then our html is super clean because here we're just having observables with a sink now the only component that we didn't implement is our to-do component so our header is ready footer is ready and now we need to render correct information but this is not that easy because here we have a lot of states first of all here in all you can see by default this markup we have here first of all is completed and then our styles is changing then on the right we have unhover this cross so we can remove the item and also we can double click and this activates edit mode so we can type something and hit enter and then it will be automatically saved inside our service so let's implement exactly this first of all i want to start with markup so let's jump inside our to-do's components and here is our to-do component so we have here justly and span and this is not enough so here i want to remove span because it was only for debugging now inside lee we need to render div with class view so let's close this div and this will be the container of our element so first of all here we have an input and this is this checkbox on the left so here is input with class toggle and here is type checkbox now after input we need to add here a label also without any events and here inside label i want to write our to-do prompts and just to remind you we have here not to do name but to do props because this is our input and here dot text and after this we need a button to remove our to-do on the right so here is button class destroy and here we are closing our button and inside we will add an event and actually here we don't need to write anything inside a button because this destroy class will add this icon now let's check if it's working at all so we're loading the page and we're typing something and here how it looks like actually not bad we have here text we have our icon on hover and we have an input on the left the next thing that i want to do is implementing this double click and edit mode so first of all here we want to add double click for our text this is why here on the label we can attach a double click now here on double click what we want to do is set to do in edit mode and as you can see my names are sometimes really verbose but this is intended because i really want to give a best possible understanding from the name and here set to do in edit mode is really clear it's not something like activate edit which is actually not bad but for example set edit is not that understandable so here is our set to do in edit mode and here let's at least create this method and here we don't get anything this is void and they want to console.log here set to do in edit mode so let's check if it's working i'm typing something i'm double clicking and you can see in the console this console log the next question is how our editing will work at all so actually when we check the example here we're double clicking and the first item is edited now we're clicking on the second and actually as you can see the first item is not edited anymore which actually means somewhere we need to store the active edited id so this is enough for us because we know okay we're editing now the element with ad1 for example then we're double clicking here okay we're editing the item with id2 the main point is that we have two ways how we can implement this first of all of course we can create inside our service here somewhere on the top new property and store there our editing id this is totally fine and this is really reusable but i want to show you that we don't always need service and sometimes it's completely fine to just store our value inside parent so my idea is that instead of service we can store our value inside main here and you may task why here because this is our parent which means it is only rendered once actually we can't really store the editing value here inside element because then we can activate editing in several elements because they are all not synchronized when we have a single value here in main we can pass it directly inside the child and this is exactly what i want to do so here inside main component we can create just a plain variable editing id and inside it won't be an observable so just a value we can have two possible values first of all it is string and secondly it is null and by default i want to save here now why i wrote it like that so first of all here by default we are not editing anything this is why here we have a null and then when we double click on something we need to change this property to our id to our stream that we double clicked and then we can pass this information in every child and our children always know are they active or not and this is really simple so here we have our editing id and now inside our main component html here we have app to do's to do and we are passing here inside to do but we can also pass something additional here so first of all we can pass editing id but we can do even better we can write here is editing so this is a boolean and here as a value we are writing editing id and this is our local property inside main equals to do id so what's the point of this code actually we don't want to give inside every element edit in id because it doesn't make any sense our small to do component should be almost stateless so we don't care about editing id there but what we want to know if our component to do is editing or not this is why here we have a comparison and this comparison gives us boolean and we are passing this boolean inside so now we need to jump inside our to do and create here one more input and this input will be ease editing and here i'm naming it is editing props because i want to know that this is props and they know that this is boolean now we can use this property to render our input only when is editing is true so let's jump inside our html and here after div view i want to add here in g container and here i have ng if is editing props so actually we're rendering this ng container only when is editing props is true and this will be rendered automatically when we are changing in our main editing id now inside we want to render our input and here we will have class edit and also a value but we will add it later one more thing that we want to do here is to add inside our li one more class when we are in editing mode this is why here i can write ng class like we already did previously and here we have an object and here is a class editing so i want to add this editing class when is editing props is inside true and the point is that we will hide this part and only show this part in editing mode but of course when we look in browser nothing new will be shown so here we see only our not editing state and the point is that by default editing id is now and we didn't change it so what we need now is on double click in this set to do in edit mode change this editing id and this is exactly a task for outputs so actually when we are in child and we want to pass some information to the parent we are using outputs so here we need to write output and here inside our name so our name will be set editing id but the main problem is here that we want to rename this also and to show that this is output then we have a different name for output and this name set editing ad can be used inside our component this is why here i want to write set editing id event so when i'm writing here at the end event it means that this is an output and here we know that this is event emitter because this is what we're using for events and actually my import is not correct so you really need to check this out and inside we know that we have types string or null and by default here we want to call new event emitter so if you didn't know what outputs is this is the way how we can emit something for parent and actually what we are writing here inside emitter this is our possible values so we can emit some string like editing 80 or we can emit now when we want to close it or remove edit instead so here we have new event emitter and now inside our set to do in edit mode we can call it so it will be this set editing id event and here the most important is emit because we can't really just call it directly we can only call it through emit and now inside we can pass some information in our case we want to pass inside this to do props dot id now we need in parent to react to our set editing id so i will copy this from here and jump inside main in html and here inside app to do studio i need to create new event set editing id now here we need to provide a local function and let's name it the same set editing id and here we need to write dollar event to get this id inside a function so let's jump into s file and somewhere on the bottom create new function set editing id and we know that here we will get our editing id and it can be string or now and here we are returning void so what we want to do here is just override this editing id property and assign here our editing id let's check if it's working so here i'm reloading the page i'm typing something here we have our element now i'm double clicking and as you can see we're directly getting our input why is that because here inside our to-do component on this function we emitted this event and we listened for this event inside our main and when it happened we set editing id when we are setting editing id we are passing in all our elements new is editing when of course it is true in our case the first element that is rendered here has true this is why we're jumping back inside to do and here we're rendering this ng container with is editing props because in this case is editing props is true the next thing that i want to do is create directly all functions that we need inside html so here i am inside to do component html and we have for example destroy so on click we actually need to remove our to-do this is why here i am attaching click and here we will have remove to do function let's create now this function inside component and just write console log site so we know that this function is already there so here will be remove to do the next thing that we want to do we have this input with toggle so here is type checkbox and we need here two things first of all is checked and here is the value directly from to-do props is completed so actually this input should be checked when our to-do is completed and we also need here a change and then change we want to toggle our to do so here let's name this function toggle to do and i want to create now this function also inside component so let's set it here this is our toggle to do and here we're returning void and we just console log our toggle to do and the last function that we need is of course key up and key enter and just to remind you here inside header we already did that here we used an input value keyhapp for change text and keyend to submit it and we will do exactly the same logic here inside to do so here we have our input for editing and here i want first of all value and here we need a property editing text so this value is not existing yet we will create it and assign by default for empty stream and also we need here two events first of all it will be key up and when we're just typing we want to change our text so this editing text this is why here i'm creating change text and i'm passing inside event to read the value of the input now after this i also need an event for key up dot enter and this will be our submitting so here we will have change to do and we don't need any parameters so now first of all in to do i want to create new function change text and here we're getting an event of type event so let's name it void and here we have console log with change text and now the next function that i will create here is our change to do so this is update of our to-do that we are editing so here also void and inside console.log change to room so this is all functions that we need to implement now so we binded all them correctly and let's check first if they are all there so here i will just type something here let's check delete i am hitting something remove to do is there the next point is here we have our input and actually it is undefined by default because we didn't create this editing text that we defined here so this value is not there this is why we just get undefined as a string but the point is when we are typing you can see here change text function and when i'm hitting enter here is change to do so all our functions are binded correctly and we just need to implement them first of all let's create this editing text property so here inside component on the top just below our output we can create this property and we know that this is of type string and by default this is an empty string but here is the point we are getting here our to-do and we want actually to set here the value after we're getting it and we can do it for example with ng on init so here i am writing implements on init and we can create here our ngoninit function so let's add it here and on init i want to write inside our editing text the value of to do this is why here will be this editing text equals this to do props dot text so we're just reassigning our editing text on initialize every time when we are initializing to the component now let's check if it's working so here i'm typing something we're getting our element now when i am clicking edit as you can see we have our value from to do so this part is working now we have our function change text and actually here we want to change this text that we created so editing text so for this here on change text we need to read the value and we already did this inside our header so here i want a value and let's write here event dot target and we need to write as html input element so we can readjust our value directly from here so our value is there and we want to override our editing text with our value now we need to update our change to do so this is the submission of our changing and here is change to do and i want first of all to log here this editing text because this is the text that we changed and secondly we need to close our editing state and for this we can write here this set editing id event and just emit here and null so in this case we will set our editing id to null so we won't have any editing element and it will be automatically rendered so let's check this out here i am typing something we have our first element now i am editing it now here we change the value i will clean the console and i'm hitting enter as you can see first of all we have change tags this is fine and here is change to do with our new value so as you can see this is the new value and our state here is not editing anymore obviously we have here the old value because we didn't change it yet but we will do it in a second the most important part that we closed our editing state and here we have our value so we can give this value to our service now the question is how we can change our item inside service because there we are storing our data so what i want to do here inside constructor we need to inject our service so let's add here constructor and add our service and this is our to-do service and here is of type to do service and here now on the bottom we can write before our emit for example this to do service and here we need to add new function of course change to do the question what we need to provide inside first of all new text and secondly the id of the item that we want to change so here will be this to do props dot id so this is the idea of to-do and secondly we are passing inside this editing text so this is our new text and id and this is enough information for us to update our to-do so let's copy the name and jump inside to do service so here let's jump to the bottom and somewhere after change filter create our change to do function so here we have two arguments first of all we have an id and this will be string and secondly we have text it also will be string and back we're getting void now the question is how we can update our to-do's so we need to loop through the to-do's find to-do by id and then update it and we can do it exactly in a way how we did here inside toggle all actually i will copy-paste this code because it will be almost the same so i copied the whole code from toggle all and here i pasted it inside change to do so what we want to do here is to get updated to do's this is why we are reading the value with getvalue here and then we are mapping every element so here if to do id equals id then we need to do some magic and if it's not equals then we just return our to do so we don't change anything now if this to-do id equals the id that we want to change so this id we need to update its text this is why here i will return new to do and here i want to spread all properties of the to do and just overwrite here the property text so what's going on here we're looping with map through our to-do's and here we have access for each to do and inside we're checking is this id of to-do equals id that we need to change if not then we simply return the to-do but if yes we're just spreading so we're returning new object and we're spreading off values of our to-do and we override the text with text that we passed inside change to do so here we got our updated to-do's which is a list of our to-do's and now here we're writing these to-do's next to update our list of to-do's now let's check if it's working so here i'm in browser i am typing something this is our element now i am editing it and i am writing here 111 and i am hitting enter as you can see our element was updated and automatically re-rendered because we changed it inside our service and all components that are listening for this behavioral subject were notified of changes and rendered the next thing that we want to implement is removing of our elements so here we have cross and here is our console.log remove to do so let's jump back inside our to-do and here is our remove to do method so we also want to create a new function inside service to remove elements from our array this is why here we will just call this and here will be to do service for example let's name it remove to do and we must provide just id inside because this is our unique identifier so here we have this to do props dot id so here we are passing our id of to do and let's create remove to the function inside our service and actually it will look exactly the same like change to do so here is remove to do and we know that we are getting id as a stream and we are returning here void so what we want to do inside is just filter our to-do's this is why here is our updated to-do's and we want to get to those and here we want to filter them so here is just get value and here we're calling filter directly on the array so here we have access for every to do and we want to reject to do with this id this is why here we're returning to do id doesn't equal id so in this case we really use filter as a reject so here we are rejecting if this to do a d not equal id so this is our array of updated to-do's and now we need to call these to-do's next to update our behavioral subject so here is our updated to-do's and let's check if it's working so here i'm typing something and now on the right we have this cross and when i am clicking as you can see record to initial state because this was just the only item if we have for example two items here and then we just remove one of them so the second item stays there so the move is working correctly and we just notifying our service that we need to update the array of data and the last thing that we need to implement is toggle to do here on the left so actually we're changing our checkbox but we're not notifying our service so let's do exactly the same here we are in our to-do component and here is toggle to do so we can create in our to-do service new function and call it toggle to do and inside for tokling we just need to provide an id this is why here these to do props dot id now let's create toggle to do function inside our service for example on the bottom so here we're getting our id of string and here is void so actually we want to do exactly the same what we did for example for update or here for toggle to do actually i will copy everything from toggle all because it will be exactly the same so we want to loop through our array and here return all elements as it is or update the element if id is the same like here so what i want to do here is remove this code and just write return to do so this is the default behavior and now here we have our if so if to do id equals our ad we want to update or toggle this property is completed this is why here i am returning the spread of to do and i'm merging it with is completed and here our is completed will be just inversed so i will write here not to do is completed so if it was true it will be false and vice versa so let's check this out here i am typing something here is our element i am checking something and this text encounter was updated exactly because of this logic so here our checkbox is just in html but here we are subscribing to our list and we know that we don't have other non-completed items so actually we created all features of to do mvc but here is the small thing that i want to improve so when we jump into edit state as you can see i can't directly type and this is not good ui this is why it will be really nice if we can add here focus so actually to attach here focus we need to work directly not with angular but with dom so what i want to do here is first of all jump in to do component html i can add new child element so here with hash i am writing text input and now we can read the value of for example do focus inside our ts file for this we need on the top to add here view child so here we have a decorator view child and here we are writing the name like it was inside html and it was text input and we know that text input is an element ref and now we also need to import our view child so all inputs are there and now we can work with this view child as with normal dom element the question is what we want to do with it and when so normally when we're just typing something and we're double clicking here the thing that is being changed is this is editing property so this props so we need to really listen to this is editing and when it is changed to true then we need to do our focus and for this we can use angular callback on changes this is why here i am writing comma on changes and let's create it here under our ngo need so here is ng on changes and here we are getting our changes which are simple changes and now here let's console log our changes so we can check what is it about so here is our changes let's look in browser we're just typing something you can see our changes because here we got our to-do props this is not interesting for us but here when i am double clicking you can see that we are getting changes again and this is his editing props and it was changed from false to true and this is exactly what we want to use so here we can write if changes and here we have is editing props dot current value which means the new value so for us is interesting when it is true because then we have this editing mode so if it is now true we want to make a focus and for this we need to write this text input native element focus let's check if it's working so i'm reloading the page type in something here is edit mode and bam we have an error native element of undefined actually it is happening because our dom element was not rendered yet because as you remember this input is inside ngif this is why here we need to wrap our code in setting mode so it will work after the rendering this is why here we are right in set timeout and here we have some function and inside we just want to use this focus and here of course we want to set second argument for zero because we don't need any delay we just need to make this after rendering so let's check if it's working so here i'm typing something this is my element i'm hitting double click and as you can see i directly got a focus because here is our ng on changes and we are waiting for hour is editing props current value and when this is true then we set time out we are focusing on our native element so we successfully implemented together our to-do mvc and yes this is a small project but even with small project we can use a lot of advanced stuff and build everything correctly and actually if it was complicated for you or you want to really learn how to build projects with angular i have an advanced angular course where we're building the real application from start to end and it is going 10 hours and if you are interested i will link it there on the description box below so don't forget to check it out and if you like this video and you want more content like this don't forget to put thumbs up to support me and of course subscribe to the channel and if you didn't like this video consider watching it once again on increased speed that might also help and i will see you in my next video you
Info
Channel: Monsterlessons Academy
Views: 33,601
Rating: undefined out of 5
Keywords: monsterlessons academy, angular todo list app, angular todo app, angular todo list tutorial, build a todo app with angular, todo app using angular, build todo app using angular, angular to do list, angular real project, angular build todo list, creating scalable angular app, angular tutorial, angular todo, angular application, todo list, angular for beginners, to do app in angular, to do list app in angular, todo list app, angular tutorial 2021
Id: uyTC0Skvvls
Channel Id: undefined
Length: 129min 19sec (7759 seconds)
Published: Thu Apr 01 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.