back to indexAngularJS 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
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: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: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.