back to index

AngularJS end-to-end web app tutorial Part II


Chapters

0:0
2:57 Directives
5:12 Angular Documentation
16:0 Add a Default Search Order
23:10 Icons
23:49 Ng-Show
27:56 Pagination
30:10 Show More Method
31:38 Optional Success Callback
41:21 The Debugger in Javascript

Whisper Transcript | Transcript Only Page

00:00:00.000 | Welcome back to our series on creating a complete end-to-end web application
00:00:07.400 | using AngularJS on the front end, and a back end written in C#. We've also
00:00:14.240 | looked at a Python version of the back end. Remember the back end is very simple.
00:00:19.120 | All it does is take some data out of a database and serve it up using JSON to
00:00:25.960 | our front end. It's in that client side where AngularJS does all the heavy
00:00:31.760 | lifting in terms of the logic display and so forth. And that's where the focus
00:00:37.520 | of these tutorials has been and will continue to be. So far, all we've managed
00:00:44.880 | to do is display a list of our todos. This is where we got to last time. This
00:00:52.760 | list of todos is coming out of a SQL Server database, or if you're following
00:00:56.920 | through the Python version, it was a SQLite database, has been served up over
00:01:02.280 | JSON and displayed. We can see exactly how this is happening by looking at the
00:01:07.880 | network timeline. If I refresh, it gives us a really good sense of what exactly
00:01:16.560 | is happening here. We asked for index.html. index.html, remember, consists of just a
00:01:26.440 | very small amount of code. All it does is it bring in some JavaScript. Our own
00:01:33.640 | JavaScript is amongst those. It brings in the bootstrap CSS and it contains a
00:01:41.240 | couple of attributes that tell Angular to display our templates within this. So
00:01:48.760 | you can see that from index.html that is bringing in jQuery, Angular, bootstrap, our
00:01:58.360 | own application JavaScript, and the template we've requested. And then our
00:02:06.080 | controller has requested the list of todos from our API. So it said "get/api/todo"
00:02:16.360 | and that brought back all of these todos. That was then displayed in the
00:02:24.320 | template. It was displayed in the template showing for each item the
00:02:34.880 | fields that we requested in a table. In the last tutorial we talked a bit about
00:02:46.640 | scope, which I said is one of or perhaps the most important part of Angular. I say
00:02:52.880 | perhaps because maybe even more important than that is the concept of
00:02:58.000 | directives. So before we go into more detail around building the application
00:03:02.640 | today, let's discuss a little bit about exactly what directives are and why
00:03:08.600 | they're so important. You'll remember from our last tutorial that
00:03:20.640 | index.html, which brings in Angular and our application, causes two things to be
00:03:29.840 | attached to each root, both some code, which is in these controllers, and the
00:03:39.240 | actual HTML pages which are in these templates. But what really is happening
00:03:45.920 | here? In particular, how is it that Angular can see things like ng-repeat
00:03:54.400 | in our template or ng-app or ng-view and make things happen? These are not
00:04:04.720 | attributes which are actually defined in HTML. How is Angular causing them to make
00:04:13.200 | stuff happen? Either by displaying things in a different way, by changing the HTML,
00:04:19.160 | or by adding behaviours through JavaScript. Well what's actually going on
00:04:24.920 | is that Angular puts an event handler which gets called as soon as the DOM is
00:04:32.840 | completely loaded, and that event handler goes through all of our HTML, and in fact
00:04:39.600 | it goes through the DOM, and it looks for special tags or attributes or classes
00:04:48.920 | and special meaning that those tags or attribute or classes are things which
00:04:56.600 | have been registered with Angular as being special, as being things that we
00:05:03.480 | want Angular to handle. And things which are registered in that way are called
00:05:09.920 | directives. Let's take a look at the Angular documentation. You can see at the
00:05:16.440 | very top of the Angular documentation is a list of directives, and you'll see
00:05:22.000 | there's basically two kinds. Some which are the same as existing HTML attributes
00:05:30.200 | or elements, and some which start with ng. You'll notice that the ng ones use
00:05:38.160 | camel case, and if you look at ng-app for example, you can see that the way
00:05:43.480 | that these camel case names get used is by taking wherever there's
00:05:50.440 | a capital letter and lowercasing it and putting a dash between. So ng-app
00:05:56.720 | becomes ng-app like this. So these directives are perhaps the most
00:06:06.520 | important foundational thing you need to understand to actually understand what
00:06:11.400 | Angular is doing and how it's working. And these ng versions are elements and
00:06:19.440 | attributes and classes which Angular has effectively added to HTML, and they each
00:06:25.560 | have their own behaviors. So for example, ng-click is something that allows you to
00:06:31.400 | specify custom behavior when an element is clicked. Well, we've looked at ng-repeat
00:06:37.920 | already, so here's ng-repeat in the documentation. It instantiates a template
00:06:42.520 | once per item from a collection, so we've seen that used before. What about these
00:06:47.880 | ones which overlap with existing HTML? Well, what happens here is that the
00:06:54.360 | Angular directive causes the existing HTML behavior to slightly change. So in
00:07:00.320 | this case, the Angular compiler goes through the DOM, finds all the a tags, and
00:07:06.480 | modifies them in some way. And in this case, it ensures that the default action
00:07:11.120 | is prevented when href is empty. Anybody who's programmed in JavaScript before
00:07:16.000 | will recognize that as being a pretty handy default behavior that it's
00:07:21.160 | created. Well, actually default behavior that it's removed in this case. What's
00:07:26.280 | really interesting, I think, about Angular is that you are not limited to the
00:07:32.960 | directives that they've provided the Angular authors. In fact, you can add your
00:07:38.960 | own. Let's say I very commonly had a header which looked something like this,
00:07:51.760 | maybe it was greetings from somebody to somebody. And maybe we want to now
00:08:08.920 | create something in HTML that can automatically build that using something
00:08:13.420 | like a greet tag. This is obviously a very silly example, but it's a very
00:08:19.640 | simple one to get the idea. So it could be greetings from Jeremy to audience. So
00:08:34.600 | how would we create that? Well, interestingly, it really couldn't be more
00:08:41.400 | straightforward. There is something called .directive in Angular, and you
00:08:50.800 | can see I've got a template for it which basically includes all the bits I might
00:08:53.800 | want. So we create a directive called greet. And literally, this is now
00:08:59.320 | registered with Angular. It tells it any time it sees this, we would like to
00:09:06.120 | attach some special behavior to it. Maybe let's make this a bit simpler and use it.
00:09:16.360 | Give. So we'll use it here.
00:09:23.840 | Okay, let's try that. So there's a whole bunch of things that we can do, but the
00:09:34.560 | very simplest one, let's get rid of everything except the template and the
00:09:41.320 | controller, because the very simplest one basically lets us insert our own
00:09:46.000 | behavior and HTML by having a template and a controller which is reusable. So in
00:09:51.480 | this case, our template would be the contents of this, and we're going to
00:10:03.280 | replace these with these things in Handlebars. So we'll go from and
00:10:11.720 | something called from, and we'll call something to. So now that we've done that,
00:10:24.760 | it's as simple as remember these things are going to come out of dollar scope. So
00:10:29.360 | let's put them into dollar scope. Dot from equals, and we can just grab the
00:10:35.880 | attributes and find the one called from, and dollar scope dot to, and we'll look
00:10:42.760 | at the attributes, and we'll find dollar attributes dot, I think we call it greet.
00:10:48.800 | So we've now got a controller, we've got a template, and let's see if that now has
00:10:56.840 | the behavior that we requested. So we'll get rid of our H2, and so now all we've
00:11:01.360 | got here is a div in which we've got our own new directive. Let's try that, and you
00:11:10.720 | can see it's done exactly what we hoped it would do. Now that's obviously a
00:11:15.440 | very simple example, but you get the idea which is using nothing but this template
00:11:20.920 | and controller we can insert our own code and our own HTML by searching for
00:11:26.400 | our own special directives. And with the other directive options that you can see
00:11:35.520 | here, you can actually put all kinds of other functionality. For example, this
00:11:41.400 | link is perhaps the one that's most commonly used that calls the JavaScript
00:11:46.360 | on the DOM element after it's being created, and that's where for example you
00:11:51.320 | could call a jQuery UI method or something like that. And then we'll
00:11:58.240 | certainly come back and create some of our own directives that are more
00:12:00.840 | interesting than this later in this series. So for now, now that we've learned
00:12:10.200 | about really what's going on with Angular, which is to go through the DOM,
00:12:13.800 | finding special elements, special classes, and special attributes which have been
00:12:19.800 | registered with Angular, and giving them special behaviors. These things have been
00:12:25.040 | called directives, and understanding that Angular comes with a whole bunch of
00:12:30.160 | these which gives us lots of really useful functionality out of the box.
00:12:34.960 | Let's now try and use some of this to add some functionality to our application.
00:12:40.200 | And we're just going to use pre-written directives for now rather than creating
00:12:46.000 | our own. So at this stage, all we have is something which can display a list, and
00:12:54.040 | we want to add some additional functionality to it. We would like to be
00:12:57.440 | able to sort it, search it, and if it gets really long we'd like to be able to
00:13:01.800 | paginate it, so we don't pull everything down from the web every single time we
00:13:06.200 | look at this page. So let's start creating that functionality, and let's
00:13:11.440 | get rid of our greeting. There we go. So the first functionality I'm going to
00:13:17.800 | create is sorting. Now, functionality like that, since it's working on stuff coming
00:13:25.800 | out of the database, needs to be handled in two places. It needs to be handled
00:13:31.880 | both in our web application in C#, and it also needs to be handled in
00:13:38.280 | JavaScript. So the JavaScript is going to have to call a method to sort or search
00:13:43.360 | or paginate and handle what comes back, and our web application is going to be
00:13:49.000 | able to have to handle those parameters appropriately. Now, sorting, searching,
00:13:54.080 | and paginating is so common that Flask Restless actually does all of that out
00:13:59.160 | of the box, so we don't have to add any code to the Python version. Unfortunately,
00:14:04.200 | however, Microsoft, although they also had all of that functionality out of the
00:14:08.560 | box in earlier versions of Web API, in pre-release versions, they actually took
00:14:13.280 | it out of the release version for some strange reason. So we're going to put it
00:14:17.520 | back in, and the way we're going to put it back in is we'll just go to my blog to
00:14:21.320 | part two, and you'll see here something called get to do items. We're just going
00:14:28.840 | to copy that, and we're going to paste it into our controller, replacing the
00:14:39.160 | existing get API slash to do. So here it is here, and you can see that this has
00:14:46.120 | now got the functionality we've requested it can sort in ascending or
00:14:50.240 | descending order by a particular field. It can have a search, and it can also
00:14:55.480 | paginate, in other words, it can limit to a certain number of records, and it can
00:15:00.240 | start at the nth record with this offset parameter. It's not very much code, it's
00:15:06.520 | just eight or ten lines, although it's slightly... well, it's not the most
00:15:14.480 | elegant-looking code, but it does the job, and it's nice that we can do it
00:15:17.920 | in so little code. So until Microsoft gets around to adding that back to Web
00:15:22.840 | API, we're going to have to modify Microsoft's code each time we create a
00:15:30.380 | new controller, just pasting in this, and of course you'll need to change the
00:15:35.200 | class name to your class name. So now that we have that, that's the only change
00:15:40.120 | that we need to make in C#. We now need to make some changes in the JavaScript
00:15:45.320 | to actually get this to do something. So since we're doing sorting, we need to
00:15:49.240 | pass in a sort parameter, and the isDescending parameter. So let's try and
00:15:56.840 | start as simply as possible, and that would be to add a default search order.
00:16:03.000 | So let's say to start with we're going to... so we're obviously going to need two
00:16:08.880 | things in dollarscope, one for the order and one for the direction. So let's
00:16:14.640 | create order, and let's by default sort by priority, and let's also do
00:16:25.120 | direction. So we could say sort underscore direction. Actually let's call
00:16:31.360 | it isDescending. That's a bit easier since really it's a boolean, isn't it? So
00:16:37.000 | isDescending, and let's use false for that. So it sorts by ascending, so lower
00:16:42.800 | numbers will be considered more important. I think that seems reasonable.
00:16:48.560 | So now that we've set those, we're going to need to make sure that we actually
00:16:55.040 | pass in these things to our web API. So at the moment we're not passing in
00:17:01.600 | anything at all. So how do we pass things into our web API? Well, let's check the
00:17:08.560 | Angular documentation, and remember that the actual API on the client side, we're
00:17:16.080 | using this thing dollar resource to call it. So let's find out how dollar resource
00:17:20.080 | works. So if we scroll down through the dollar resource documentation, we
00:17:30.360 | eventually get to what it returns, which is something that we can call get save
00:17:34.840 | query etc. And here we can see that for the get actions, the first thing that we
00:17:41.920 | can pass in is parameters. Here's an example of it here, a parameter name and a
00:17:45.480 | parameter value. So in our case, our parameters are sort and desk. So let's
00:17:54.320 | pass in sort, and that's going to be dollar scope dot sort order, and then we've got
00:18:04.120 | desk, which is going to be dollar scope dot is descending. So we've set them, we're
00:18:15.560 | calling them, in the controller we are doing something with them. You can see
00:18:22.600 | here, if sort is not null or empty, then we order by with the appropriate
00:18:28.960 | descending or ascending. So that should be everything that we need. So let's see
00:18:32.920 | if we now have that working. So we can see we've got a problem, desk equals
00:18:40.480 | undefined, and sort equals undefined. So let's find out why it is passing in
00:18:45.840 | these unhelpful things. And here's the problem, we're calling search before we've
00:18:53.880 | set them. So let's move that to the bottom, and really we're always going to
00:19:00.440 | want that at the bottom. That's great, so here we've got it sorted by priority. So
00:19:12.520 | the next thing we want to do is we want to make it possible to click on a header
00:19:16.840 | and have that change the sort order. So let's think about what that's going to
00:19:22.560 | do. So we're going to have a function that the HTML template will call, and
00:19:29.000 | that means that that function needs to be inside dollar scope. So there's going
00:19:34.360 | to be a function, let's call it sort, and it's going to take in the parameter
00:19:41.280 | which is what column do I want to sort by. Let's call that column, and I think
00:19:48.440 | what we want to do is have it, so if you click on it once, then it will sort
00:19:54.000 | ascending, and if you click on it again and again, it will just change the sort
00:19:58.800 | again and again. For now, let's just get it so it sorts ascending every time. So
00:20:05.600 | we're going to now go dollar scope dot sort order equals that column, and now
00:20:18.400 | after we sort, we're going to have to recall search. Okay, so we've set the sort
00:20:28.240 | order to the thing we've been passed, so now we just need to make sure that
00:20:32.120 | clicking on a column will actually call this method. So since it's inside dollar
00:20:39.600 | scope, that means that we should be good to go. All we need to do is add a a tag.
00:20:52.000 | We don't need an href, what we need is a ng-click, and we need to call sort. So in
00:21:04.600 | this case it will be sort by, let's check what it's called before I type that, sort
00:21:10.880 | by text. Okay, so the first column is called text. Well of course I could have
00:21:20.840 | seen that down here easily enough, couldn't I? Anyway, that's fine. So sort
00:21:24.480 | by text. So let's now refresh this. We can see this is now hyperlinked. Let's try
00:21:33.960 | clicking it, and we can now see that it's sorting. It's sorting in a slightly
00:21:39.320 | strange order just because I filled it with numbers, but normally we would have
00:21:42.360 | text in here, not numbers. This is actually meant to be the description of
00:21:46.920 | the method to do. So each time I click on it, I wanted to change order. So let's do
00:21:52.680 | that. So in other words, what I'm saying is if these two are already exactly the
00:22:04.640 | same, then what I want to do is simply change the direction. So to change the
00:22:18.480 | direction, let's just reverse is descending. Otherwise, let's set the sort
00:22:30.320 | order and set the direction to being ascending. Let's try that. So the first
00:22:44.480 | time I click it, yep, the second time, yep, that's great. Okay, so that's done
00:22:50.480 | everything I want there. So the only other thing I might do is to make it so
00:22:55.200 | that a little icon will appear telling me which direction I am sorting in. So icons
00:23:01.440 | are rather conveniently available inside Bootstrap. So let's start by finding an
00:23:09.120 | icon that we like. So to show icons in Bootstrap, you simply use the "i" tag and
00:23:16.480 | you give it a class of icon and so we're going to have to have an arrow down and
00:23:27.760 | we're also going to have an arrow up. Now we need to display these depending on
00:23:36.320 | whether or not something happens. So we're going to have to wrap them in a
00:23:39.560 | span and we're going to display them or not depending on whether something is
00:23:47.200 | true or not inside Dollascope. So to do that we use ng-show and that simply
00:23:52.880 | takes an expression that will evaluate to true or false. So in this case we will
00:24:00.320 | show this if, let's have a think about that, so we'll show that if sort order is
00:24:13.040 | to do and also sort or is descending and since this is down that would be true.
00:24:31.400 | And we have basically the same thing for the other one
00:24:41.360 | except of course this now becomes false. So let's try that. So currently there's
00:24:51.200 | no icon shown because we're not sorting by to do and now that I've clicked on it
00:24:56.600 | oh it's still not showing. Let's try and figure out why. Oh because of course it's
00:25:03.400 | not called to do is it it's called text. Let's try it now. Okay so the first time
00:25:11.920 | I click and then there we go the second time I click that's great. So we can now
00:25:18.720 | use that for, in fact we can basically use that whole thing for each one of our
00:25:25.400 | column headers. So this one's going to be priority and then the last one is going
00:25:39.680 | to be due date.
00:25:50.280 | There we go. So hopefully what you're thinking at this point is that seems
00:25:55.800 | like a whole bunch of duplicate code and you would be right. So what I've actually
00:26:00.600 | done in the written version of this tutorial is I've shown a directive which
00:26:08.160 | automates all of that. We're not going to write it now but let's just take a look
00:26:13.920 | at it and then you can try this for yourself. So you can see we've done
00:26:19.360 | basically what we had last time which is we had a template which does all that
00:26:23.200 | stuff and in this case they've also pulled out the logic around whether to
00:26:28.060 | show or not into a scope method and then in the controller we define do sort and
00:26:34.480 | do show. So it's really pretty straightforward to turn that into a
00:26:39.320 | directive. In order to save a source of time I won't do that now and have you
00:26:44.320 | watch me but I'd love you to see you try it for yourself. So I've just refreshed we
00:26:49.440 | can now see this is showing correctly that's very good and if we click it
00:26:54.240 | twice. So one of the nice things here is I love the way even when I refresh so I
00:27:00.120 | haven't clicked anything and my default sort order is priority. Angular has
00:27:04.480 | automatically figured out that it needs to put this arrow here because this ng
00:27:09.180 | show directive it's automatically figured out when it has to check that. So
00:27:13.720 | all this kind of dependency management around when do you have to test for the
00:27:17.680 | truth of things or when do you need to run the things it's all handled
00:27:20.960 | automatically and that's certainly something that I look for in an MVC
00:27:26.840 | framework and Angular does that really nicely. Great so we have sorting working.
00:27:34.160 | What should we do next? I think for our next thing we might do pagination. So
00:27:41.720 | pagination we need to have an offset and a limit and each time we get more we're
00:27:50.780 | going to have to append it to our previous list. I should mention the kind
00:27:56.360 | of pagination I'm doing here. I'm not going to do that old-fashioned style of
00:28:01.200 | pagination where you get a whole list of pages at the bottom from like one to a
00:28:05.080 | hundred and you click which page you want. I much prefer the approach to
00:28:09.400 | pagination which is you can basically ask for more items to be shown. This is
00:28:14.920 | done for example in infinite scroll type frameworks where as you get to the
00:28:19.680 | bottom it automatically loads more or else there could just be a hyperlink
00:28:23.880 | which asks to show more. I'm going to use the hyperlink approach for now just
00:28:29.120 | because it's going to be a little bit easier to explain. So let's put a
00:28:32.540 | hyperlink at the bottom and so again we're going to have a ngClick and that's
00:28:45.920 | going to do a showMore. Now we need to write that of course and then some text
00:28:54.960 | for it. It's an equal sign there of course. Great. So we've got something to
00:29:04.840 | click on that's basically all we need to do on the template side. We need to now
00:29:09.360 | create this showMore. So if you think about it logically what is showMore
00:29:15.080 | going to do? It is going to be such that each time you click on it it's going to
00:29:21.660 | load another however many, let's say 20, another 20 things out of JSON API and
00:29:30.400 | going to append them to whatever is already displayed. So whatever is
00:29:35.800 | already displayed is called $scope.items. Now again let's put some
00:29:42.600 | defaults here. So how many things to load at a time?
00:29:47.980 | Oopsie dozy. Let's call it limit. Let's say 20. Okay and then we have what's the
00:30:00.960 | offset to start with? Now of course that's going to be 0. So we now need to
00:30:09.860 | create our showMore method and so let's do that. Now because we're calling it
00:30:15.760 | from the template that means it needs to be inside $scope. So
00:30:20.080 | $scope.showMore doesn't have any parameters. So what do we want to do
00:30:29.720 | here? Basically we want to go the offset should be equal to whatever it was
00:30:39.480 | before plus another 20. And then after we do that we now want to rerun our query
00:30:53.280 | basically to query some more. So that is called $scope.search at the moment.
00:31:06.520 | There we go. So the next thing we need to do now is to use these offset and limit
00:31:13.960 | parameters inside our query. Now interestingly though what we want to do
00:31:18.520 | now is not just go $scope.items= to do .query. We actually want
00:31:23.720 | to wait for the query to finish running and add those items to the end of what
00:31:29.200 | we already have. So if you look at the $resource documentation on
00:31:35.160 | Angular you'll see that actually you can have this optional success callback. So we
00:31:42.840 | don't have to say in fact you can see it used right above. You don't have to say
00:31:46.700 | actually let's just look here. You don't have to say left-hand side equals the
00:31:51.440 | result of the query. Instead you can say run the query and when it's finished
00:32:00.600 | call some function and that's where we write this function. So it's going to be
00:32:06.000 | passed the actual data that it's received and that's where we can do
00:32:12.840 | something with it. So to have it just continue to work as before it just be
00:32:16.320 | like so $scope.items= whatever data we were given before and that will
00:32:20.960 | continue to work just like it used to. But we actually want to do something
00:32:27.760 | else now. We actually want to say OK, pass in our offset and pass in our limit.
00:32:41.400 | And so now we're going to be given an extra 20 items that we want
00:32:54.400 | to add to the end of $scope.items. So we now need to not replace it but concatenate it
00:33:04.680 | with our new data. So this time we should only get 20 back. However we have a
00:33:19.000 | problem which is currently we're trying to call concat on something that's empty.
00:33:22.080 | So let's make sure we started out not being empty.
00:33:27.600 | OK, let's try it again. That's better. You can see we just got 20 this time. Let's
00:33:41.280 | try clicking show more. That's great. So now we've got 40 and show more again.
00:33:51.920 | Now that's actually only have 50 in here. So one nasty thing with this UX that
00:33:57.640 | still says show more when there's no more to show. So hopefully you can figure
00:34:01.240 | out pretty easily how to get rid of that. All we need to do is add an ng show and
00:34:12.600 | let's create something called hasMore. So how do we know if there's more? Well
00:34:17.800 | more or less we could basically say well if we manage to pull back at least 20
00:34:24.400 | last time. Sorry if we manage to pull back exactly 20 last time then there's
00:34:29.400 | probably more. So let's say that to start with it's going to go more equals true.
00:34:42.160 | Let's create the function hasMore. I mean maybe this is overkill. Maybe we
00:34:53.280 | hardly even need a function but never mind. So we'll just go return more. So I
00:34:58.360 | guess we probably could have done without a function at all. That's OK. That
00:35:02.200 | should be inside dollar scope of course. And now we need to check to see whether
00:35:09.200 | we got at least 20 items or not. And if so we will say that there's more to get.
00:35:16.560 | So we could say here more equals data.length equals 20. OK let's see how
00:35:39.560 | that looks. So refresh all that. So this is showing that's good. Still showing
00:35:49.120 | that's good. That's great now it's disappeared. OK so that's going pretty
00:35:55.080 | well. So we now have pagination working nicely and we now have sorting working
00:36:01.320 | nicely. So the only other thing we need to add is search. So if you look at the
00:36:07.640 | bootstrap documentation they actually have a nice little example of how to
00:36:12.760 | create a reasonably nicely styled search form. And so I've actually turned that
00:36:17.480 | into a template. So I'm just going to use that which is my bootstrap search
00:36:23.120 | template. I've also put some basic stuff in here for my NG click as well. So your
00:36:30.840 | search template can really look pretty much the same every time until you want
00:36:34.120 | to get more sophisticated with styling it. Let's have a look at what's in the
00:36:38.080 | template. So it's a form with the appropriate bootstrap classes to make it
00:36:42.320 | look decent. And the actual input box where you're going to type the
00:36:48.000 | search it has an NG model of query. So in other words anything that we type into
00:36:52.680 | this is going to end up inside dollar scope query. And I think we put into
00:36:57.240 | dollar scope query is going to end up in this text box. And rather nicely the
00:37:02.560 | submit the reset button we have set to be disabled if not query. In
00:37:10.680 | other words it's disabled if there is nothing typed into the query box or more
00:37:16.280 | precisely if there is nothing inside dollar scope dot query. So in fact I just
00:37:20.920 | wanted to show that even without adding any JavaScript we already have some neat
00:37:29.120 | behavior which is look that's currently disabled and as soon as I type here it's
00:37:33.360 | enabled and as soon as I delete all the characters it's disabled. So you can see
00:37:39.080 | with the angular directives you can actually do quite a lot even without any
00:37:45.360 | code and have everything work quite nicely. And of course you can add your
00:37:49.080 | own directives to add your own functionality again so that you your
00:37:54.360 | designers and so forth can actually add functionality to your applications
00:37:59.160 | without having to write any code. I think that's really cool. So in this case when
00:38:06.200 | we click on the search button we're going to call something called reset.
00:38:10.960 | And when we click on the reset button we're going to call something which is
00:38:16.060 | basically to empty out the query and then call reset again. So let's write
00:38:21.760 | reset. So what's reset is going to do is it's going to it's going to really start
00:38:32.360 | again in terms of what's displayed. So if I've pressed show more a bunch of times
00:38:36.640 | and then I do a search then I really probably only want to show the first N
00:38:43.280 | of that search. So I'm going to grab all of this stuff here and I'm going to move
00:38:50.560 | it into reset. There we go. And when I've done all those things I'm going to call
00:39:06.720 | search. So that's basically all I mean by reset. And so now rather than calling
00:39:14.240 | search here I can call reset. There we go. I think as you change searches we
00:39:26.080 | should probably leave the sort order as it was so I'm not going to move that
00:39:28.680 | inside reset. We're just going to set everything up from scratch. Now we
00:39:34.720 | actually want of course to make sure that we do a search. Now you remember
00:39:39.440 | that inside our control our controller we had this parameter called Q and that
00:39:47.320 | is the thing that if it's defined we're going to call dot where on it. So we need
00:39:53.140 | to stick something into Q. What is that something? It's dollar scope dot query. So
00:40:00.720 | let's try that shall we. So here we're going to add Q and we're going to set it
00:40:08.480 | to dollar scope dot query. I don't know that we need to do anything else at this
00:40:15.480 | point. We've defined what dollar scope dot query is from our template. We've
00:40:19.960 | pasted in the controllers doing something with it. So hopefully we're
00:40:25.000 | going to be right to go at this point. So let's try it shall we. Let's search for
00:40:31.440 | 6. Nothing happened but there's no error either. Let's find out why not. So if I go
00:40:41.560 | to the network tab and click search again. Okay so currently our search
00:40:47.880 | button is not actually doing anything. Let's find out why not. First of all
00:40:53.720 | we'll check our template and there is in fact an NG click connected to it so
00:40:57.960 | that's good. And then we do have a dollar scope dot reset so that's good. At the
00:41:11.840 | end of that it calls a search so that's good. So let's try and figure out what's
00:41:20.920 | going on by using the debugger in JavaScript. Let's make sure we actually
00:41:24.720 | get to dollar scope dot reset shall we. I'm just doing a refresh first and then
00:41:34.800 | I'll type something into search and click. Okay so something's happening
00:41:41.560 | that's good. Let's try it. So we step step step step step. Let's go into search.
00:41:51.280 | Oh that's interesting this time it did work. Perhaps I just forgot to refresh
00:42:05.360 | last time. So let's take the debugger out, save it, do a refresh and let's try it.
00:42:15.960 | Search. Oh there we go. So just all that happened last time was I forgot to
00:42:20.760 | refresh and therefore I had my old version of the JavaScript. Let's try
00:42:24.600 | reset. Oh that's great. Let's try doing a sort and then do a search. That's great
00:42:33.460 | that's continued to work as well and let's try doing a search and then a sort.
00:42:39.640 | That's interesting. So in this case when I clicked on the sort header it's
00:42:45.240 | actually added to this and that's a bug. And if you think about it the reason
00:42:49.920 | that's a bug is because I am NOT doing my reset after I did my sort. So let's
00:42:58.080 | change that so that it does a reset here. So in other words each time I'm doing
00:43:07.120 | something that's not show more I actually need to start again and not
00:43:12.400 | append each time. Let's try that. Do a search and then a sort. Great. Do a reset.
00:43:21.800 | There's no show more here because there's only five things to show. Do a
00:43:25.400 | reset. There's a show more. Let's make sure it's all show more works. Looking
00:43:33.320 | good. Once more and no more to show. That's great. So we're now at a point
00:43:40.320 | where we have successfully got search and sort and pagination working and we
00:43:48.600 | did that all from scratch in I think well under an hour if I'm counting
00:43:54.000 | correctly. And I think that really shows that once we've got the basic
00:43:58.340 | infrastructure in place it just gets faster and faster to add additional
00:44:02.720 | functionality to our application. I'm going to leave this tutorial at this
00:44:08.360 | point because I think we've got more than enough to keep this going for now.
00:44:12.440 | See if you can follow through with this and create add that functionality to
00:44:16.520 | your own application. Of course don't forget that you can follow through the
00:44:21.720 | written tutorial and tutorial 2 in the written tutorial goes through all of
00:44:26.360 | these steps. As this points out in the next part we're going to look at creating
00:44:31.640 | deleting and updating items and as you'll see it's going to just keep
00:44:36.680 | getting easier and easier and easier. Thanks very much for listening and of
00:44:41.760 | course feel free to leave comments either on my blog post or on YouTube with
00:44:46.880 | this video and let me know what you thought or if you have any questions.