Master Angular Fundamentals by Building a Real App | Irek Mirgaleev | Skillshare

Playback Speed

  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x

Master Angular Fundamentals by Building a Real App

teacher avatar Irek Mirgaleev

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Lessons in This Class

28 Lessons (52m)
    • 1. Course introduction

    • 2. Home list section introduction

    • 3. Generate the app and add UIkit

    • 4. Declare /homes route and add a new component

    • 5. Add mocked data

    • 6. Add service and fetch data

    • 7. Show home details

    • 8. Add styling

    • 9. Add spinner

    • 10. Home filtering section introduction

    • 11. Add filters buttons

    • 12. Add dropdown with home type filter and the toggling state

    • 13. Add form for home type filtering

    • 14. Capture selected filters

    • 15. Set selected filters in the URL

    • 16. Refactor home list to use command pattern

    • 17. Filter homes using URL parameters

    • 18. Add default filters and the highlight to the button

    • 19. Home search section introduction

    • 20. Add search component

    • 21. Add form control

    • 22. Output search to the query params

    • 23. Filter homes by search

    • 24. Set default search value

    • 25. Show empty message

    • 26. Update filtering to work with search

    • 27. Make search case insensitive

    • 28. Throttle API calls by using debounce

  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels
  • Beg/Int level
  • Int/Adv level

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.





About This Class

In this course, you will learn how to use angular framework to build an example of a home rental application. I will show you how to fetch a list of homes from a simulated backend, show a spinner and display the data with a clean responsive style. Then, I'll show you how to build a dropdown that allows you to select home types, click apply update the URL and filter the list homes. These might seem like trivial features however as you will see it shows you how to use:

  • angular routes and the router service

  • angular forms

  • custom input and output property binding

  • ngIf and ngFor structural directives

  • the async pipe and the observables

  • different styles of fetching the data from the API

  • CSS flex and grid

  • UI state management with component properties

  • ng-template with template variables

  • ng-container

  • ng cli

I will not waste your time going over any slides or theory. I keep every video short to the point where show you how to build one specific thing that you can apply right now in your next angular application

Moreover, with every video, I include two links. The first link shows what I added or changed in the code precisely line by line so you never lose track of what's happening on the screen. The second link takes you to the stackblitz page showing both the code and the application live as I wrote it for that specific video. This is super useful because you can make changes and poke around the app for every topic completely on your own without having to type the whole thing as you go along

If that sounds exciting, sign up now and start learning!



Generate the app and add UIkit

Declare /homes route and add a new component

Add mocked data

Add service and fetch data

Show home details

Add styling

Add spinner


Add filters buttons

Add dropdown with home type filter and the toggling state

Add form for home type filtering

Capture selected filters

Set selected filters in the URL

Refactor home list to use command pattern

Filter homes using URL parameters

Add default filters and the highlight to the button


Add search component

Add form control

Output search to the query params

Filter homes by search

Set default search value

Show empty message

Update filtering to work with search

Make search case insensitive

Throttle API calls by using debounce

Meet Your Teacher

Class Ratings

Expectations Met?
  • Exceeded!
  • Yes
  • Somewhat
  • Not really
Reviews Archive

In October 2018, we updated our review system to improve the way we collect feedback. Below are the reviews written before that update.

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.


1. Course introduction: and this course, I will show you how to use angular framework. To build an example of a home rental application, I will show you how to fetch a list of homes from a simulated back and show spinner and display the data with a clean, responsive style. Then I'll show you how to build a job down that allows you to select home types. Click, apply, update the Ural and filter the list of homes. These might seem like trivial features, however. As you will see, it shows you how to use angular routes and vowed er service, angular forms, custom input and output, property binding structural Angie if an 84 directives and many more concept essential for building really APS in angular, I keep every video short where I show you how to build one specific thing that you can apply right now in your next angular application. With every video, I include two links. First Link shows what I added or changed in the code precisely line by line, so you never lose track off what's happening on the screen. Second link takes you to the stack blitz page, showing you both the code and the application live as I wrote it For that specific video. There's a super useful because you can make changes and poke around the AB for every topic completely on your own, without having to type the whole thing as you go along. If that sounds exciting, sign up now and start learning. 2. Home list section introduction: in this section, I will show you how to generate a new angular application, set up the routing, mock the backend data, build a service for fetching that data and build a component that will use this service and then show the spinner and show homes in the clean, responsive style. 3. Generate the app and add UIkit: before we can generate our brain new angular application, we need to make sure that we have NGC Alliance told in our system for that. Let's run NPM in stole angular Seelye with the G flag, and now we can use it to generate our brainy application. So we'll do you in g New and then the name of our project, which is home rentals and hit Enter. And then it is asking if we want routing in our application and we say, Yes, we would like some pre configured routing. And then the next question is about CSS engine for application, which, to my preference, I will choose less, and then it generates our application, and after that we can use a mangy serve command to serve it. But let's change the directory to go into our project. And then from here we can run command in G. Serve to serve this new angle application locally and see what it looks like. All right, open It's in the browser in local host 4200 and this is it. So now the next step is to you add. You like it CSS framework to it. For that I go back to the terminal, Open another pain. Where I go into the directory with our project and then Rhonda Command to open the code base in visual studio code and NVs code, I find index html file, which is the main template off our application. And then here I will need to paste the references to you. I could see a says framework before I can. Pasty, you're else with the CSS and JavaScript. Um, I need to get those you are also I go to you like it installation guide and in there find these links pointing to Cdn, Vusi, ASUs and Joe's Group and just paste them in the head section off the template. Now, after that, everything should just work. So reloading the up, nothing seems to be broken, and we're good to proceed to the next step. 4. Declare /homes route and add a new component: once we have our app created, let's define it the default route and the component. So go toothy, conveniently generated by NGC Ally routing components where it has does default routes array. And in that ray there find the only route that will have in the application, which will be homes and that route. When you access it, it will load homes component. And since homes component doesn't exist yet, let's go to the terminal and generated using NGC Ally Command that is in G generate components and then the name of the component homes. And I'll add US flag for skipping, generating the tests, since we don't need them. All right now, here I can import this newly generated component using V s code auto import feature. And when I go to the application and go to the homes route, I see all these standard stuff in the template, except that in the router outlet portion we can see the output from our newly generated components. Now, let me remove all this extra stuff that is pre generated in the application so that it's not distracting. So go to app, component html and just select everything except the router outlet that outputs are components that are routed and delete it and save it. And now we see that it Onley shows with router outlet shows, which is under the home's bath. It is our newly generated homes component. Now I'd like to fix one thing notice. When I go to the default bath, which is nothing, it doesn't show anything. Ah, and that's because we don't have anything set up in the routing that will display anything under the default route. So what I want to do is declare a new routing rule were I will say that when you go to the default drought, which is nothing, just empty string. I'd like it to read direct to our homes route, which will be our default route if we do it this way. And then I have to specify bath match mechanism to be full for the resurrect to work now in the application. If I try to go to the default drought, it properly redirects me to the homes route. And just to confirm that this displays the content off our newly generated homes component , I'm going to open the homes component templates in V s code and here it is. I see that it shows the exact string that I see in the browser. Now I'm going toe do one little thing, which is I'm going to to remove the that less file for this home's component. It is for styling, and we're not going to do any extra styling for this component. So I'm just going to remove it and remove this reference from here. Now reload The EP. Just make sure nothing is broken and it's looking good. 5. Add mocked data: now, before we can start writing code that will show the homes for listing and do all the styling and all that, we need to have some sort of mocked data that we will pretend that the back end returns to us when our application is asking for a list of homes to display. I'm going to do that by going into the Assets folder of the application and creating a new file which alcohol homes dot Jason and it will be a Jason file that will be one big array off objects where each object will be will be representing a individual home, and each home will have a few properties. 1st 1 will be image Ural, which will contain the link to the image for the home that we will display in the white and then another property. It will be type which later we will use for implementing the filtering capability where you will be able to filter by types such as apartment house were room and then another property will be location, so have so that we just have it to show it in the U. Y. And then the last property will be title, which is just purely for the display and demonstration purposes as well. And I just make up whatever the values for these properties. And then I'm going to have a bunch of these objects for each individual home in this list where each property will be something different, worth least some variation of it. All right? And that's all we need to mock the list of homes so our application can display it in the UAE. 6. Add service and fetch data: Once we have mocked data to display in our obligation, the next step is to create a service that will Fitch this data. So here I use in GC lie again. I say in G generate service and then the name of the name of the services data. And again, I skip generating the tests since we don't need them. And once the service is generated, gonna open it here, envious, cooed and declare the only method that we will need at the moment and it will be get homes . And then here I'm going to return the result off using http client in its get method to query or to request the homes Jason file and from our assets folder. However, we need to make sure to import issued to be client module in our application. So I need to go to APP module and then here I'm going to add an import for each day to be client module on top of the file and then make sure to import it inthe e imports array right here. Now go back to the data service and here we should be able to inject or http client and I declared as a private property. See each to be client and it will be the instance off HTV client from angular core. Now, once we have the data service that is capable of fitting homes, we're going to inject it into our homes component right here. Make sure you imported a top of the file and then we're going to create a property on this component which will be homes with a little dollar sign indicating that it is an observable . And then we're going to assign into the property of the result off calling, get homes, all of the data service. So now we have this property that refers to the observable, and we can use it in our template. So I'm going to do something very simple here. I'm going to refer to the homes property, and I'd like to pass it through the Jason pipe so I can just see the results off what it returns from the back end. And since it is an observable, I need to make sure that I subscribed to it using the A sink pipe. And if I reload the page, I see that the template successfully fetched the data using the data service from the Assets folder, and it is displaying that data directly on the page. Now we can start building out functionality that will display each individual homes in a nice styled fashion. 7. Show home details: and since our component now has access to the home status, we can start building out the functionality for displaying that. So let's come into out this piece for a moment and start by creating a title for the component, which will be homes in H one tag. And then here it sticks to the edges of the page too closely. So I'm going to place that into UK container as, ah component declared in You Like it CSS framework. It just adds some nice padding and margin to it. Well, it adds margins. I'm going to add a little bit of padding to it as well. And then when I place home inside of it and reload the page now, Holmes is not sticking to the ages too closely. Now let me grab this subscription that we create using a sink by right here and then use it to create this div with Angie for structural directive, where I declare a loop that uses the system subscription like that, and then it has access to each individual home to display just like this, where I can show the title for each individual home and here after reloading, you can see that it lists titles for all the homes that we have declared in our mocked file . Now I'm going to go to you like it card components and seeing example off where they have cards with images. It's all the way almost at the bottom, and here is unexamined. So I'm just going to grab the example HTML from here and paste it in my template. And I'm going to remove this UK card default class since I don't need it. And the first thing I can sit is the image. And remember, each home has emit Uriel property that refers to the image. So I'm just going to specify right here and I'll delete the Alz property and then next in the cord body, I'm going Teoh show home type and home location. Actually, I'm going to put those into a separate div so that I can have another def next to it for showing the home title. And that makes use off all the properties that we have in the home. And after reloading the page, we can see all that displayed using you like it card formatting 8. Add styling: Let's do a little bit of clean up around this styling. First, let's remove all this extra padding around home type location and the title, so I'm going to remove the batting from the body. All right, this looks a little better, and then I'm going to add quite a bit of styling to type and location. I'm first going to make the text, mute it, and then I'm going to make it uppercase, and I'm going to make it smaller and I'm going to make it bold. And finally, I'm going to make sure that it is truncate when it is too long to display in the card. All right, this looks great. Now, with the title, I'm only going to make sure that detects is bold. Using UK text bold glass. All these classes are coming from you. I kid CSS framework. Alright, individual home looks good. Now, however, if I expand this page, everything is displayed in the single column. So let's fix that. I'm going to create a new day of year that will use UK grid formatting from you like it, and I'm going to place the piece of code that generates all the homes inside of that new DIV. So every home is in the CSS grid. Now, if I expand the page, it generates the grid. But I don't like how it shows only two columns when the pages full full with. So let's make a couple of adjustments here. I'm going to add a class and use the with utility classes from you like it to say that every child in the grid must occupy 30% of the with. Now, this looks almost good when I expand the page. It looks good one when but when the pages small three columns is too many. So I'm going to add a designation to this glass that will say to apply it on Lee on small screens and bigger. That means that when the screen is small, there will be on Lee Single column because every column will occupy 100% of with have ever . If I start expanding the page, it starts being bigger than small, and therefore the class is being applied in. We see three columns here and now it looks great, And just one tiny little adjustment I'd like to make here is to make sure that the height off every cell in the grid matches, so it looks even a little bit better now. It's perfect and we can remove this commented out peace and we're done for this video. 9. Add spinner: when we reload our application, notice how the list of homes is displayed almost instantly have ever remember that list is coming as a result, Off making an A P. I call against Holmes Jason file where we mock our homes and that is in the a synchronous school against our assets folder. And it returns so quickly because it is served from the same server as this application. However, that is rarely the case for really applications and riel AP I. Cole's takes take a little bit longer to complete. So now let's go ahead and simulate what happens when we add an artificial delay to our coal to fetch the list of homes. For that, I'm going to use the pipe function on the observable that returns the lifts list of homes. And I'm going to add the delay operator from our ex Trieste that allows us simulating two second delay where it will wait for two seconds before returning the list of homes. All right, and when we reload our application, we see that the page title appears right away. However, the list of homes takes a couple of seconds to appear, and during that hour, page just looks blank, which is obviously not a good user experience. So what we're missing here is some kind of indication that the data is being loaded from the back end. So let's take care of that. Let's go into Thekla opponent templates. And here, let's revisit how this works. So this part is subscribing toothy homes observable, which makes that a P I call in the data service and then in this Angie four loop, it generates a whole bunch of these homes inside of the card showing home details. So what I'm going to do here is extract or copy this part that subscribes to homes and then place it in this separate div inside of in G. If structural directive essentially subscribing to the list of homes inside of this Angie if and then giving it a name as a variable name as homes but without the dollar sign. And then I'm grabbing the part that contains the A G four loop in older cards and putting it inside of this div with the NGF statement and what this allows us to do here is that we can grab the homes of variable that we declared here and then replace the original subscription here of the A sink pipe and just use their homes variable. And then we reload the page, everything, just working the exact same way. So nothing changed here. However, what this allows us to do is that in this in G if statement were, we subscribe to homes and declare homes variable. We can also declare an else statement and then specify which portion off the template must be displayed when the homes observable did not receive any homes from the A P I yet. So I'll cold this portion off the template loading just like this. And then down here, I'm going to declare that portion of the of the template using Angie template directive where I will give it the name, the loading just exactly the same as I specified in the n g of statement. And here I'll just type in loading just to see that it works. And here who? And I reload the page for this couple of seconds when we're rating for the response from the back and we see loading is displayed right here. So it is working all right, but showing just loading word is pretty lean. So that's why let's go to you like it, spend their components and grab the examples. Oh, how to show spinner and stick it in here instead of the loading word and reload the page. And here we have a nice little spinner. That's much better. I just want to make it a little bit bigger, setting the ratio off three. That looks better, and it just needs to be aligned to the middle. So all said the glass Ah, using UK line center and UK text center. And that should put the spin spinner in the middle of the page just like that, all right, and this completes our application. 10. Home filtering section introduction: this section, I will show you how to add filter buttons, including a job down with check boxes where the users select home type click supply. And then the application updates the Ural with selected filters and filters the list of homes while highlighting the active filter button. 11. Add filters buttons: I'm going to start by adding some comments in this template to separate the main sections. So this one will be home list with the loader. And now the main section that I'm working on will be filter buttons. So the first thing I'm going to out here is a parent, Div. Then there will be another DIV inside of it, which will have the button with the first filter, which will be home type. I'm going to copy this first if and based it a couple of more times and turned them into two more filters, which will be dates. Angus. Reload the page and see the buttons display here. That's good. Next, I'm going to style these buttons by adding UK Button UK Button Default, UK Button small and UK text. No rap classes from you. Wake it and apply same glasses to the rest of the buttons just like that. Next thing I'm going to do is to declare class in this parent DIV, which is UK margin, which will add a little bit of space underneath the button and the first home in the list. Them going to add UK flex glass to display the buttons in line instead of being stacked just like this. And then I'm going to add UK grid small class which will add small Gardere in between flex items and now it looks all nice and tidy. 12. Add dropdown with home type filter and the toggling state: let's add a little job down to the home type filter button were in future. We are going to place check boxes for filtering the list of homes by home type. So all start by declaring a new diff, which will be the job down. And then I'm going to add a class to it that will say UK job down, which will turn it into a job down component from you Like it CSS framework. And I'll have it to be open by default by assigning UK Open class. And after reloading the page, we see the job down. So that's good. And let me just make it a little bit wider by assigning UK with medium glass to it. There, this looks better. And now let's take care of the ability to toggle this job down, on and off by clicking in the home time button. So first I'll add this energy of statement that will look into the property that I will name home type job down open that will contain a bullion value. Sure, Fels that will tell whether the job down should be closed or open after reloading the page , the job down disappears because this property doesn't exist yet. Therefore, Angular considers it to be full C and hides the job down. Next, I'm going to bind to click event on the button, and when you click on the button, I'm going. Teoh update Home type. Drop down open property to be one, which is the cruelest true, and that should open the drop down. Saved the page. Click on the button and here's the job down. It shows up, however, right now there is no way for me to close it, so I'm going to update this assignment here, too. Instead of always assigning one. We just true to assign the opposite value off what's currently stored in the property and that Will Targo value from true to false, depending on whether to drop down is open or closed, and now the drop down appears and disappears when I click on the button. Now, let's take care of this rid highlight by opening the component controller and declaring this property and a sign the default value false to it so that when the component is loaded for the first time to drop down is closed 13. Add form for home type filtering: now inside of those drop down for home type button, I'm going to declare a component that will represent a form with chick boxes for filtering homes by their type uncle, it at home type filter and then in the terminal. I'm going to use NGC Ally to generate this new component. As usual, I'm going to skip generating the test file as we don't need it, their ego. And now let me just go into thief older with a component and delete the less file for styling because we're not going to need a here and delete its reference from here as well. Their ego now reload. The page opened the job down, and we see the default string from our newly generated components, and here it is, in its template. All right, so let me start here by declaring the main form element, and inside of there I'll start by declaring the first label element, inside of which I'm going to add an input element, which will represent the very first check box for filtering. I'll add UK check box glass, you it for some styling and said the native type to be the check box in the name of this check box will be for filtering by apartment type. All right, 1st 1 is good. So with me, copy this here and here and turn it into a couple of other check boxes. So it will be for filtering by room type and by house type. And after that, let me add a button for applying these checked boxes that will, in future will reload the page and filter the homes. All right, here All the elements was Just apply some styling to it. And for that, I'm going Teoh, declare this main div here in place. All the elements inside of it, in turn, does Main Div into UK Grid just like that. And then I'm going to add a class to this grid that will make all Children the with off 100% so that they stack and go one after one after another just like this. And then I'm going to add quite a bit of styling to this apply button. I'm going to turn it into ah UK button, and then I'm going to add a link style to this button, and then I'm going to make it large, and then I'm going to align it to right and also add some small margin around it. All right, this looks almost good. Just the supply button is miss positioned little bit. So let me take it out of this main Div and place it here and now. This looks great. 14. Capture selected filters: Now let's add the ability to see which check boxes the user selected. After they click the apply button, I'll start by going into APP module and importing forms, module and reactive forms module from angular forms. Now let's go to our form component controller and inject form builder just like that, and then use it to build a representation of average shaped boxes. So we'll use foreign builder and say, Create a group which will be an object representing each chick box so it will be apartment room in house. Now let's declare this actual form property, which will be the form group just like this, and then go into the template and update the form element to connect it to our form, using its form group input property just like this. And then I'm going to bind to the submit events of this form when the user clicks on the apply button and I'm going to execute a submit methods while passing the value off check boxes, whether they are selected or dot just like this. So now let's go into the controller and declare this submit method and remember it except form values. And for now I'm just going to Consul. Log these values now. Reload the page. Select a couple of check boxes. Click apply, and it shows every check box. As we declared it in our form, however, it doesn't show which check boxes were selected to fix that. Let's go into the template again and then manually connect each input check box here with its respective property in the form that we've built in the controller by using form control name input property from angular forms just like this. Now try again to select check boxes. Click, apply, and now we see which check boxes were selected. 15. Set selected filters in the URL: all right. Now let's see how we can sit those selected filters in the current Ural Query parameters. I'll start by navigating into home type filter component controller and in the submit button, I'm going to add a bit of good that will process form, value object that contains selected filters where I will use object keys, native method from JavaScript to turn this object into in the ray that I will then filter by whether the check box is selected or nuts. Now, let me output what I've got here in this home types of Ray just to make sure it's working properly. So, like department and room click apply. And now here we see a plain old ray off. What exactly is being selected now I can work with that. So next I'm going to declare an output property in this component that'll name applied, and it will be an event emitter back to the submit function. Here. I'll use this output property and the vent the Mitter to emit a new event that will pass the array of selected filters, now, navigate to the homes components and bind to this new output property just like this, where Each time the user clicks apply, it will execute home type filter, apply method and pass the array of filters. Now go to the controller of homes component and declared this new method home type filter applied and it except the event was selected filters. And in here for now, I'm just going to console log whatever I've got. Just to make sure it is receiving proper data on red. Reload the page, select apartment in the room, Click, apply, and now chose the same exact thing have ever It is the data that we see from our homes component. Okay, Now I can delete the council log statements and replace it with a coal to the navigate function off angular router. Just like this, I will set it to navigate to homes bath, which is the exact same path where we are right now. However, I'm going to specify new query parameters where it will set the new parameter alcohol home type. And it will be the array off selected filters just like this. Now, let me inject angular router in this component. Looks good. Now reload the page. Select apartments and room click apply. And now we see that it set the inquiry parameter, specifying what we have selected. That's perfect in one last thing I'm going to do here is to sit home type, job down, open property to fools as soon as I click, apply so that the job down disappears when the great parameters are set. Otherwise it'll stay open, which will be weird. Alright, let's try again, said department in room Click apply. And now not only the query parameters are set, but also the job down disappears perfect. 16. Refactor home list to use command pattern: now, before I can make use of those filters, said inquiry parameters, I need to re factor homes components to use a command pattern for fetching to data and showing this spinner. I'll start by updating this assignment, where the component grabs the reference to the observable with homes to instead of calling , get homes methods on data service to simply reference the homes observable. And then in N G. On innit method. I'm going to Coal Data Service Load Homes method that I'm going to declare in just a bit. And this will be a sort of a command for the data service to start loading the homes so that in our observable online 13 we can receive him. All right now, let's go into the data service and rename this method to load homes and remove this return statement. Since it won't return anything. And now let's declare this new homes property, which will be, ah, behavior subject from our extremis with an initial value oven empty ray. Now let's finish implementing load homes method by subscribing to the result off calling the get method to retrieve the array off homes right here and then grab that array of homes and push it into the homes stream so that homes components can receive it and displayed on the page. Now let me just add the type things here to get rid off the red. Squiggly. Alright, looks good. Now go back to the homes controller. Let's reload the page and it's almost working as expected, except that it no longer shows the spinner to fix that. I'm going to go into the templates and grab this whole bit that displays the spinner and put it inside of the Div, where we subscribe to the list of homes. All right, I'm going to update it to be in G container instead of entry templates. And then I'll remove the else statement from this structural NGF directive. And then I'm going to add and g if, to this contain over spinner where it will look. If Holmes array has any items, and if it doesn't, it will show the spinner now reload the page spin there is displaying and everything is working as expected 17. Filter homes using URL parameters: all right, Since we have our filters, said in your real query parameters, we can use them to actually filter the home list. So I go into you homes component controller, and here I'll inject a reference to the current route using activated route service from angular router. Then in a G on in it, I'll use the service and reference query parameters observable and subscribe to it just like this, where it will receive the parameters from the euro. And for now, let me just try to output them and see if I got it right. When every load the page without any query parameters, it shows nothing. And when I said something in the council log, you can see there with references. The said filters. All right. Now let me create this new variable that I will use for grabbing the list off, said Filters. Just like that. And now let me try to output it, and we can see that now It's simply in the ray off selected filters. That's good. Next I'm going. Teoh, move this data service log homes method inside of this query Brams subscription just like that, and then pass the array of filters to it so that when it's loading homes, it can filter them. Now, go inside of data service into the load homes. Update the method signature to indicate that now it receives the selected filters. And ideally, I would have passed this list of selective filters along with the A p I coal, so that the filters can be applied on the server side and on the application in front and side. I could just receive already filtered list. However, we don't have such capability in this example. So I'm going Teoh filter the list of homes on the front end side using map operator from our extremis. I'll add a little comment here to indicate that and inside off our map function, I'm going to return a result off filtering the received homes by weather. The current home type includes one of the selected filters just like this. Remember, Every home, according to our data in the Jason File, has the type right here so that we can filter it in our map method. Okay, reload the page. Let's try to set apartment filter and apply, and now we see on Lee the apartment type homes, so that's good have ever. If I remove the equal parameters and go straight to slash homes, I will see the spinner that just spends forever and never shows the list of homes to fix that. I'm going to update my filtering function here to add a guard to check. If there are no filters, set Adul, then simply return the entire list of homes without attempting to filter it. Now reload the bait without great parameters, and it shows the spinner and the last kink to Iran out here is this. After initial page load, when I select their filter and click apply, it looks like nothing is happening for a couple of seconds. And then the list of homes is refreshed with the filter applied. So it doesn't show the spinner when we're filtering the homes. And to understand why that happens, let's go inside off our homes controller again. And in this subscribed function, where we subscribe to query parameters, we extract filters from the great parameters and then pass him to load homes method in a side of load homes method. We received the list of homes, filter them and then push them into the homes stream where our template is parsing that stream in showing the list of homes. However, if you look at how the spinner works, it will only show up if the list of homes is empty. And that never happens in the flow that I just described Now there are many ways to fix that. But what I am going to do is go back to the data service and in the Load homes method. I'll simply add a statement that will push an empty ray inside of a home's stream just like that. Now, reload the page, try to apply a couple of filters, and now we see the spinner perfect. 18. Add default filters and the highlight to the button: Now, if you've noticed when we have filters set in the Ural and the list of homes is filtered, and when we opened the job down with filters, it doesn't show that there are some filters are currently selected. Now, to fix that, I'll go to homes component and declare new property for current home type filters. And now, in our subscribe function to the gri parameters, I'm going to sit this new property to whatever the home type filters are coming from the quarry parameters Now go into the templates and use input property binding to pass this list off selected filters into the form component that displays individual check boxes. Now, this is highlighted rid because default filters property doesn't exist on the home type filter component yet. So lets navigate inside of those components and declare this property. Now, let me just try to output this in council to see if I got the property binding, right? Reload the page and it shows the currently selected filters. Now I can use it for each individual check box here in our form group builder to check whether to full filters. Ray includes each individual filter just like that Okay, now reload. The page opened the job down, and now it shows the selected filters. Now for the last nice touch, I'm going to navigate to homes template and use a G class property binding on the button for opening the job down and I'll sit UK button primary glass from you Like it. If current home type filters array has any items in its now, reload the page and we immediately see how home type button gets highlighted because there are selector filters. Now, if I reload the page without any filters, the highlight disappears and let me test it again. Opened the job down. Select apartment. Quick apply. We see the button, gets highlighted and receive the spin there is spinning, and then it shows the filtered list of homes. And then when we opened the drop down again, it properly shows the selected check box. What a delightful user experience 19. Home search section introduction: in this section, I will show you how to add functionality that allows searching homes by title. As with the filtering, this will include the ability to share the Ural that will produce the exact same result. Additionally, will make sure that searching works nicely in conjunction with the existing filtering function. You also learn how to show a helpful message way in. No homes fit the searching criteria. And finally, I'll show you how to limit the number of a P I calls. The APP makes as the user types in the search string so doesn't congest the network. 20. Add search component: all right. The best spot to put the search field here will be underneath these existing filter buttons . So for that, I'm going to go in open homes templates and find the spot in the code. Were those existing buttons and and add a component here that will represent thesis, urge Field. And since it doesn't exist yet, I'm going to go into the terminal and use NGC Ally to generate one. So it'll be n g generate component home search just like this. And now if I reload the up, I see the default string generated by NGC allies showing up right here. So that works. And as usual, I'm going to delete the styling file and the testing file. Since we're not using those in this tutorial and then remove the mention of the styling file from the component right here just like that, So that looks good. And the next thing I'm going to do is to go to the documentation for you like it, CSS cream work and find the component for showing the search field and just copy the snippet that they have here that contains the search icon. Here it is, and then go into the templates off the search component and pasted right here. So now when I reload the up, we see this search field showing up. The only adjustment I'm going to do to it is to add UK with medium class to make it a little bit bigger. So it fits. The current layout will be better. Looks good. 21. Add form control: all right. So now we have the field where the user can type in the characters and that we need to find a way to get access to those characters the user is typing. So for that, I'm going to import form group from angular forms and then declare property called form, which will be an instance off this form group and then all import form builders. So I can build that form group and all injected here and the constructor and then in a G on in it, I will use it to build the four just like this by using group method and this method except an object which is a representation off your form. So in our case, we will only have a single search field like this. And now in the template, we can connect the existing form element to the form group that we just created and then connect this input element to the surge elements from the group using form, control, name, property and the value of this property will be the search field here just like this. So now we can get the reference to this search field from the form and subscribe to its value changes observable so we can run some custom code each time the user enters a character. So for now, I'm just going to consul. Log that value and let's see what happens. Reload the APP. And each time I enter character, the entire string gets displayed in the council. All right, as an overview here, we created a form group with a single search field in there and then in the templates, connected that to the form element using form group input, and then connected this input field to the search control name, which allowed us to subscribe to value changes and get access to the values admitted by the search field. 22. Output search to the query params: all right. Now, since we have access to the search string, the users typing, let's take that in. Add some logic that will put that string into three euro query perimeter as a search choir parameter so that from there we can add some future code that will refresh the list of homes. So to do that, I'm going to import the output decorator here and use it to create an output property that all cool applied. And it will be an instance off event emitter that I'm going to replace this council log statements to emit a value each time the user types in the character. All right, And now in the homes templates, I'm going to copy an existing example of binding, toothy applied output property that we have in our home type filter components right here and then paste it for our home search component. So here I'm just going to rename the methods that I'm going to call each time the search outputs a value to search applied. And now in the controller, I'm going to declare this method. So it's search applied all right, and I'm going to update this bit that updates the your reliquary parameters to add the search query parameter. All right, now reload the up and you can see as I type in the string, it is instantly added through the query parameters, so that works perfectly. 23. Filter homes by search: all right, So now let's try to grab an existing string from one of the home titles and try to search using it, and we can see that it doesn't work. It returns all the homes, regardless of wood. We type in the search, so let's actually make it work now. For that, we can use the existing logic that listens toothy changes in the career parameters and then reloads homes accordingly right here. So I'm going to create a new variable, which will be whatever the value is in the search query parameters and then pass it to the Load Homes method as the second argument and then added, here in load homes Method signature just like this. So I have access to it and then remember the Load Homes method works by fetching the list of homes and Jason format and then filtering out by its type and then pushing the filtered lists into this homes stream, which we have declared here, which were referenced in our Holmes component right here, which we use in homes templates right here by subscribing it, using a sink pipe and listing all the homes. So now I'm going to use the exact same approach for filtering homes as we do by filtering them by type. I'm going toe filter them by the search string in a title. So here I'm going to you apply the same guard by checking. If there is no value in search string, then don't filter old. Any homes just returned the entire list. However, if there is a value insert strength, then keep on Lee the homes that in its tattle includes that search string, in other words, that match the search criteria. And then this filtered list of homes gets pushed into the stream. All right, so now when I have refers to page, the quarry parameter contains the search string, and we see that the list of homes gets properly filtered. Let's see how we did it again. We grabbed the search string from the query parameters and passed it to Load Homes method where we used it to filter out the homes that don't have that string in its title and then push that filtered list of homes into the stream 24. Set default search value: All right, Now, notice how I type in the search string here, and it properly updates the Ural. But as soon as I reload the page, um, the search string remains in the Ural as it should. But the search field here loses this default value, so that's not the expected behavior. When I load the page with the search query pre filled, the search field here should reflect their default value. So to fix that, I'm going to use the same approach as I did with home type filters. Right here. I'm going to declare new property that I'll call current Search. And then in our subscription to the creep parameters, I'm going to set a value to this property, which will be the whatever Search string is coming from three euro query parameters when the page first loads and now in the template, I'm going to copy the line that already does this thing for home type filter component and paste it for our home search components. So name this input property default search and then pass whatever the value in the current search property that we just created. So now I go into the home search and import in import decorator and use it to create that input property that we just used in template. Remember, it's default search like this, and now I can use it to specify the default value of the search field in our form group right here. So as a result, when every load the page with search query parameter containing the value that value is added as the default value of the search field. 25. Show empty message: Now there's a problem with current implementation notice. If I try to search for a non existing home, the loading spinner just continuously spins and never stops. That's obviously not a desired behavior. Instead, it should show something like no homes found instead of spinning forever. So why this happens right now is if we if we go to the Daughters service Ah, here we filter out older homes that do not match our searching criteria. So in the end, what we end up pushing into the stream is an empty array. In our template, we have this logic that shows the spinner when the list of homes is empty. So to fix that, I'm going to update the homes stream to push not just on array of homes but to push an object that will have a couple of properties. The 1st 1 will be a Boolean for loading. That will indicate if the list of homes in the process of loading or not and the other property data will be the actual list of homes now update this line here that executes as the very first thing when you try to load homes and it pushes empty list of homes into the stream to indicate that it is empty. So now I am making it. Teoh indicate that the loading flag it is true. That means loading isn't process. And now here everything is executing as usual. But in the end, when the list of homes is fetched in processed and filtered, I'm going to push into the stream again. This object where loading will be false, indicating that the loading is complete, and then into the data property goes the list of homes, whether it is empty or not. So now, in our template, I'm going to update the block that shows the spinner to use that loading property instead, just like this. And then I'm going to copy it and paste here and use it to show a message for the scenario when there are no homes found as a result of searching and the criteria for showing that message will be that if the loading flag is no longer true, that means the list of homes is loaded and that if the data array, which contains the list of homes, if its length property is zero, that means there are no homes, and therefore it will show the sign for no homes found. And then I just need to update the N G four loop to loop over the data property in the home stream because that's what now contains the list of homes. All right, And now, after reloading the page, if I search for a non existing home, we properly see the message for no homes found. So that's a desired user experience. And still, if I try to search for existing home, I still find one so everything works as expected. 26. Update filtering to work with search: Now there is another kink to iron out in our current implementation was tried to search for home that house downtown word in that Steidl. So we get to homes here and one off type room and the other one off type apartments. All right, so two different types. And let's say I want to filter out further this list to show on Lee the apartment types of homes. So I select apartment in our home type filter here. Click apply. And what happens is that it updates the search query by removing the search query parameter from here in only leaving the home type filter. So what happens to the list is that it on Lee shows the old the importance that we have in our entire list and completely ignores our downtown search stream. So that's an indication the ads, using search and filtering at the same time just doesn't work. So what, instead should be happening? We and you apply one filter or another. The application should preserve both in the U. R. L. So here it would have looked like you pick home type the apartment right, and then the search query should remain just like this. So let's go ahead and fix that. And all we need to do is to update these two handlers that's update euro query parameters when you try to filter homes by type or when you're searching them. So 1st 1 for updating the URL for home type filtering here, I'm going to you create this new variable cold Haram's, and I'm going to grab the current query parameters from Route Snapshot like this. And then I'll created new variable that is the home type we want to filter in, and I'm going to grab it from the current implementation here and paste it here all red. So that's an object for home type filtering. And then I'm going to use those to a newly created objects to merge them, using spread operator into a single object that will represent a sort of combined query parameters that will have both the existing query parameters and the new one specifically the home type that we want to filter by. All right, now I'm going to copy this implementation and paste it in the handler for searching homes. And here I'm gonna update this home type property to be search just like this and then update this variable here. All right. And now searching functions should preserve the existing query parameters. So, for example, if you selected home tied filtering and now when I go and reload the ab, So here we have selected home type filtering by apartment. All right, so that works as it should. And then I see one home here house, downtown, keyword in there. So I'm gonna pace that here and search by that keyword. And now we see that both filters have applied properly. It's only the home type off apartment displayed here in the only one that has downtown Key Ward in there. So now, filtering by many things in conjunction at the same time works properly. 27. Make search case insensitive: So here I have searched homes by downtown keyword where the first letter is capital just like this, and it finds the results. However, if I switch that first letter to be lower case, it stops finding any homes. And that's obviously not the desired user experience. It should just ignore the case and find whatever matches the curry. And that should be as easy as going to the data service, where we or filtering homes by title, according to which is searching for here to first transform the title to lower case and then transformed the search string to lower case as well. So the case is completely ignored in both the home title and a search string, and it should result in showing older homes that have downtown keyword in there, regardless whether it is upper case or lower case. 28. Throttle API calls by using debounce: all right. There's one last thing that can be improved in this app. Here, uh, notice when I type in the search query here, Each time I enter a character, it issues another AP I call to get the list of homes. That's obviously not a desired behaviour because it makes the AB slower. Recon just's the network and instead, it should wait a little bit until I stop typing. And then it should make us a single ap. I cool. So fixing that should be as easy as going into our search component here and here We have our subscription Teoh monitoring. Each time the user enters a character in it, um, it updates the parent components in parent component makes the A P I. Cole's right. So here I'm going Teoh, uh, stick a pipe in front of the subscription like that and then imports D balance time operator from our ex dress and put it in the pipe with 500 milliseconds value just like this. So what that's going to do is is each time when I type in, the character in the search field is going to wait for 500 milliseconds until triggering the subscribed function and therefore issuing the P I call. And in fact, when I try to type in the search strangers like this, it waits for 1/2 a second. And then, um it's the value to the parent which triggers the single AP I call, so that's much better.