- Overview
- Transcript
3.5 Filter Edges
In this lesson we'll add filters to our edges page. We'll see how to use ng-options and test drive our own custom filter.
1.Introduction1 lesson, 01:12
1.1Introduction01:12
2.Application Setup2 lessons, 17:25
2.1Front-End Application Setup10:37
2.2Backend Application Setup06:48
3.Public Area7 lessons, 1:37:56
3.1Routes, Navigation and Directives12:06
3.2Unit Tests and E2E Tests With Protractor15:24
3.3Testing With Capybara04:39
3.4Display Edges on the Page16:46
3.5Filter Edges22:35
3.6Testing Boundaries of Two Applications14:39
3.7Acceptance Tests With Capybara and Factory Girl11:47
4.User Section5 lessons, 1:04:12
4.1Front-End Login Form and Validation12:54
4.2Token Authentication27:56
4.3Create New Edge10:32
4.4Refactor09:36
4.5Delete Edges03:14
5.Conclusion1 lesson, 00:31
5.1Conclusion00:31
3.5 Filter Edges
Hi, in this episode we'll add filters to our edges page. So, let's get started. So first of all we want to be able to search through all edges, so we want to have here some kind of a search field. We type something and we narrowed down the list of edges displayed to us. So let's implement this. It's very easy to do in Angular. First of all, let's add this search input field. So we go to edges.html, and right here we're going to have div with class form-group. And instead of this div, we'll have input with type search. A name search. And we do not to have here a value, because there's going to be an ng-model. And we will store these in a model called filterBy. So filterBy will be an object that will have search string in it, because we will have several filters. So we will have here search and class form-control. Okay. So, let's have a look and here it is. So now let's introduce this model that we created here in the controller. So we go into controller edges and right here on this scope. Let's define filter by as an object where we have search string as an empty string. So now to add the search functionality, all we need to do is add filter right after pipe. Right here in the ng-repeat. So when we have here, ng-repeat-start edge in edges, and we add pipe here and tell to filter it by our filterBy search string. So now if you go back to browser and type the here something, you can see how it narrows down. Great. What important to remember is searching happens in all fields. So for example if a, if I want to get combat, you can see that it filters down to combat. Or for example if I want to have all novices, I search for novices. So maybe that's not the behavior that you want, maybe we want only to be able to search by names and other filters will serve us to narrow down by category or by requirements. So again, it's very easy to do an angular, we just need to surrounded by curly braces. And specify what attribute we want to filter by. So, for example, name. Now when we save it and go back to browser and try to type novice nothing happens, because now we actually search by name. That's pretty good for a couple lines of code isn't it? Okay, so now let's add another filter. So let's say we want to see only background edges or only combat edges. So we want to have here the drop down list, where we select for example background, and whole background is there. So let's go back and I'm going to introduce now the div with class row. And this one will have class col-xs-3. I'm going to copy it. And the next one also will be the same thing and inside of it I will have the select tag with class form-control like this and also let's close up div and for both of them let's add labels. So, label for this one is search and label for this one is category. Let's save it and go back to browser and you can see now that we have category. But now we need to populate this drop down list somehow. So, let's go back to our controller. And we make very similar thing here, so here we will have categories, and we will use categories service, and let's edit here as well, like this. Now we need to create this service, so I'm going to open service edges and copy this thing. And now in this folder I'm going to create categories.js. Past it into here. So that's gonna be a categories, and this then will return cat-array, like this. So basically we have the categories service that will return three, three types of categories. Background, combat, and leadership. And also, I want to have another object that will tell us, all. So, in this case, and that which is selected by default, all categories are selected. So let's save it, now we need to go back to index.html and add this service as well to the index page categories. So now that we have categories at our disposal, let's populate select with it so let's go back to edges HTML. And here we have the select. So first of all let's give it a name category. And next we need to bind it to the model. So we'll have ng-model. And that value of this model will define which element of this select is selected. So it's going to be a filterBy category. And the last one is ng-options, which will populate select with options. And it's pretty weird syntax, it takes sometimes to get use to it, but basically let's start from the end. So we have category in categories. But in categories as you saw, categories is just an array of objects. So we need to dive deeper and to take the name of it. So to take the name we do c.name for. So what are we doing? We taken the category name for category in categories array. Let's save it. So now if we go back to browser, you can see that we have all these options populated. So now we want by default that all should be selected. So let's go back, let's go to our controller edges, and here in filterBy we add category. And to assign category, it takes not a string but an object. So we take this $scope.categories array and take the first element of it, the first object. So now if we save it and go back to browser, we'll see that by default all is selected. So now when we select category here, for example background, we want only background edges to be displayed here. So for that, let's create custom filter. So in HTML file that we have here we can actually stack filters together. So we can add another pipe here and say, edges. And this is going to be the filter name, edges. And we want to provide as we did here the filterBy object. So what happens, this edges filter will receive edges collection, and filterBy object, which we will use to return another collection, filtered by this filtered by object. Okay, so let's save it and now let's create filter. For that, in apps scripts, let's create another folder, we call it filter, filters, and inside of it. File edges.js, and we need to create it. So again, as usual, use strict, we take angular module, our application, and filter, we'll call it edges, function. And now, we need to add this filter to the index page. So, let's go to index.html and add here, filters, edges. Okay. So now we're ready to implement filter. And, let's do it again, test first. So, let's create new tests for our filter. Let's go to test/spec. And inside of here, we will create filters/edges.js. Again, make folder for that. And we're going to describe here our edges filter. So, as usual, we need to make the beforeEach and load up our module with our application. And then we need to inject to our test this edges filter. And edges filter is just a simple service object. So what we do when we want to inject service objects into our test? We set up beforeEach inject function, and then here, we specify this service. Filter service is just different in that, that it has the suffix filter. So we define it as edges. But here, we'll do edgesFilter. And, that's all that we need to do. So inside of it, let's sign it up to filter, like this. And we need to define this filter here. So now we're ready to describe our first filter. So we're going to describe category filter that we want to implement first. So now, first of all, we need to have some data, so let's create edges. And there's going to be just an array of, say, two edges. And each edge will have just a simple category with a name of first. And the second edge will have the category with a name of second. Okay. So now we have edges, and we need also a filterBy object that has category there with the name of first. Okay, so now we have data, let's create examples. So, the first example is, it filters by category name. So basically, we have two edges, and when we have in a filterBy, we have the category with the name first, only this first, so, only one edge should be available. So let's test it out. So we expect that filter, which is here, edges filter. And we pass two options to this filter, edges and filterBy. And, it will return the collection, that array. So we want to make sure that the length of this array to equal 1. Because there's only edge with category first. So let's save it. So let's go to terminal and run karma. And, of course, it fails because undefined is not a function. So let's go back to filter edges, and filter should return function. So, we return function. And this function takes, in our case, two parameters, edges and filterBy. Okay, so if we go to our edges.html again, you'll see that we have edges filter. And, it takes the collection of edges from here, from ng-repeat, and filterBy from our parameter here. So the first parameter is provided by ng-repeat. And the second parameter provided by us. So let's go back. So now here, we can return edges and we want to filter them. And this filter function takes the callback, which has the element in it, index, and array. So in here, we want to return some kind of a comparison. So we want to compare element category names. So we return element.category.name. So element in this case is the edge, so we take the category of the edge and its name, and we compare it to the filterBy.category.name. Let's save it, go to terminal, and we're green. Great. So that's the most basic example. Let's create another one. So the second one is about all. So, it returns all elements when category filter is All. So, we change filterBy.category.name to All, and after that, we expect that filter with edges and filterBy, length to equal actually 2. So, all two edges should be returned because category name is all. So if we save it and see, it fails, because it returns zero, because it doesn't know what to do with this all variant. So let's go back to implementation. Okay. And to implement it is very easy. We just add very simple condition. So, if filterBy our category.name equals to All, then we simply return edges without any changes. All right. So now, when we save it, we're back to green. So, as you can see, it's very easy to test filters. All we need to do here is inject filter and filter's just a simple service with aa filter suffix to it. And then you just test it as you would test any other object. So now, when we have it, let's have a look in the browser. And you can see that when we change for example category to background, it automatically filters it. Combat, combat, how cool is that? And of course, we also can narrow it down by typing something in search and now we have background brave functionality. Great! So the last thing, and it's kind of an optional, but we'll do it anyway, is to add rank filter. So here is the rank. This novice thing is the rank of the hero. So let's add another drop-down menu for the rank. So let's go back to our HTML, and here I'm going to duplicate this div, and there's going to be a rank. So here again, rank. And in filterBy, also we have rank, and here as well, ranks. Okay. So now, we need to have this ranks. So let's go back to controller edges, and here in the filterBy, we will have rank, which will be the same thing, scope ranks, and the first element of it. So now here, we duplicate and we want to have ranks as a different service. So, let's create a service, in services, we're going to, I'm gonna add, I'm going to open categories, and copy it. And now let's create, in services, we're gonna create ranks.gs. Paste it into here. And here, I'm gonna add ranks, and it will return All, Novice, Seasoned,. And that's all for now. Okay. Next I need to go to index.html, and add it here as well as service ranks. So now I need to go back to spec for filter edges, and here we will have another describe log for rank filter. So basically, let's shift this initial data from this describe, to before each, right here. And I'm gonna go in to remove this vars. And just do it right here. Edges and filter by. And now here in rank, I want to describe it filters by rank function, so now I need to add to this ages also, and now the thing like requirements that we have in our data model. And that's gonna be an array of different requirements. And the first one will be with name null and value Novice and that's gonna be mode rank. And now the requirement will be something like. Agility. With a value of d6. And it's not going to be a rank. It's going to be a trait. So we will have different kind of requirements. And it's very important to make it automatic for character generation process, but not in this course. so what we need to do, is we need to get this rank with this [UNKNOWN] novice. And ignore all other requirements. So this is how requirements look like right now. So, I'm gonna copy it, and here we will have seasoned. So if you go back to our test, we'll see that they are failing on line 16. I have problems with okay, that should be comma, let's save it, go back, and now we failing because we do not have rank provider, so let's go back to our control edges and ranks ranks, okay, mistype here. Let's go back. And now we're back to green, excellent. So that's, another way, why test are awesome. Because these kind of typos and regressions are very quickly found. And it's quite amazing. So now we're ready to describe our filter by rank. And let's add, here, filterBy. We have the category. And we want to have the rank, which is also, will be the object with name. And for now he's gonna be a Novice. Okay. So filter by rank. Basically we expect most of the same thing. Like we expected here. So, we expect that edges filter by with length to equal one. But, we need to change filter by category name to all, because now we want category all but rank novice. So and in this examples, quite the opposite. Here we want to filter by rank name equal to all. Okay. Let's save it. And it should fail, and of course it is. It returns two, but we expect one. So let's go to implementation. So what we do here. We will return not this then, but we will return category and rank. And these are two things are going to be booleans. So, let's define category, and category will be equal to element dot category name equals to. Filter by category name, or if filter by category name equals alt. Okay, so there's the category. the next one is rank, and rank is a little bit more complicated, because we actually need to find, the rank object into the requirements array. It also return filter by rank name, if it equals to all it return true or, and we need to introduce another function. We call it get rank, element requirements. So we provide element requirements to get rank and it iterate through the requirements and getting the rank. And the value. So these things are obsolete now, and let's define this get rank. So there's a function which takes requirements, and inside of it we have requirement that we want to find, and then we iterate and if reqs requirements with this index mode equals rank,. Because there could be a lot of other modes like trades, skills, etcetera. And then we want to set this raq to raqs with this index and break the loop. So, and by the end, we want to return req.value. So we do not have here, the protection from, what is there is no requirement like rank, and so on? But that's quite enough for now. So now, if you go back, we're still failing on expected token. And of course, it doesn't work. Because, here, we have, get rank, element requirements. And it should be equal to, filter by rank name. Let's save it, go back, and now we're green, excellent. So we could add another example. So make sure that filtering works as it should. But I leave it up to you. So, and if you go to browser and try to filter it by rank. Value we have only novices, and we have only seasoned. And, for example, if we have novices, and we want to have only background, here we are. And we even can search, and that's pretty awesome. so let's commit this change. Filters for ages. Okay. In this episode, we saw how to use filters and angular and we wrote our own custom one, and even tested it. The time has come to implement back end, and make sure that everything works with end to end tests. So thank you very much for your time, and see you in the next episode