2.1 The New Controller
The next step is to allow our users to create a new contact. For this, we'll need a "new contact" view, and a controller to go with it. That's what we'll create in this lesson.
1.Getting Started7 lessons, 55:14
2.Core Features6 lessons, 1:04:12
3.Finishing Touches3 lessons, 42:11
4.Conclusion1 lesson, 02:02
2.1 The New Controller
In the previous screencast, we built out the table that will be displayed on the main page of our web application. And this is where users will be able to see a list of all of their contacts. However, to create the contacts that we were showing in that table, we had to hand edit the JSON file that is the back end of the database. Of course, we can't allow our users to do this. So in this screencast we're going to begin to create the new contact form where our users will go to create a new contact. [COUGH] We're gonna start this screencast in our public/src/app.js file. As you might recall, this is where we have our route provider. And currently, we only have a single route being provided. When the route is /contacts, we will display the list controller. Let's add another route here. I'm gonna say when the route is /contact/new, then in the object here we'll set the controller equal to the NewController, and we will set the templateurl equal to views/new.html. So, with this in place, we can now actually create this controller and template. We're gonna start with the template. So, open public, views/new.html, and this is going to be much simpler than you might expect. At the beginning, we'll start with an h2 that says new contact, and then, underneath this, we want to create our form. So, we have our form element like this. However, it's not gonna be your traditional form element, because it's not gonna have an action or a method. Instead, we're gonna give it a name newContact. Now, the name property on a form is important to angular. By adding a name to this form, we'll be able to access this form from our controller by doing $scope.newContact, and this will access our form here inside of our template. Now, why would we wanna access this form from inside of our controller? Well, the reason behind that is validation. If we want to be able to validate our form, we have to have a way to access it, and so this is the way that angular gives us to access our form. Now we wanna add some other properties here as well. We're gonna add another angular directive which is noValidate. And the noCalidate attribute basically turns off the native browser validation. So we don't want the browser to validate our form for us, we want to do it ourselves. And, finally, let's add a class for bootstrap. This is going to be form-horizontal. Now inside this form you might expect that we wanna put a bunch of input elements so we can have all of the different fields of our new contact filled in. However, that is not the case. Although of course our form will need to have input elements, we're not gonna use just any old input element, as we would do if we weren't using Angular. But because we are using angular, we're gonna create some directives that will allow us to edit our contact fields in a more intelligent way. We're gonna build those directives in the next screencast and the one after that. However, we do have some other things that we need to finish up in this form while we're here. Let's create another div. And this is gonna have a class of row and also a class of form group. And then inside of this, we wanna have another div with a class of column, or col-sm, for small, offset-2. And this is just gonna offset whatever we put inside of this by two column widths. This is using the trail bootstrap grid formulas. So inside of this, we wanna have a button. And we'll add the class of btn and btn-primary to this button. And we also want to add an ng-click directive. And when this button is clicked, we're gonna save the new contact that our user is adding. And we'll give this button the text, Create Contact. Okay, so right now, this is all we want to do in our form. We're gonna come back and add some stuff above here in future screencasts, but for now, this will do. So, now, we want to create our controller, cuz remember over here when we made our route, we set our view/new template, and then we also want to create a new controller. So let's open up our controllers file which is public/src/controllers. And we only have one right now, list controller, so let's add another. And that is going to be the NewController. Or callback here will of course take Scope. We will need our Contact factory and we'll also need location from Angular, just like we took in the list controller op above here. So the first thing we want to do is create the contact object that user will be editing when they're in our new contact form. So basically what this means is we're gonna have scope.contact and we're gonna go ahead and create basically a blank contact object. And then the user will go ahead and fill in all those fields on that object and then at the end we can go ahead and save that object, so it actually becomes an object in our database and not just in our code. So we're gonna say newContact and we can pass an object to our newContact here and this will be all of our different fields. And what we're gonna do here is have all of the fields that we want our contact to have by default. So let's add some fields. As we saw in our previous screencast, we want all of our contact instances to have a first name, so we'll go ahead and add that in here. Now, remember the format we're using from the previous screencast where we wrote some data into our data.json file. We have our field name and then we have an array of two values. The first is the value of the field and the second is the type of the field. So this is how we have to do this. I'm gonna copy and paste this and we're gonna have our last name. Let's also go ahead and have email. Now email the type is gonna be email, because the types that we're using here are the types of input elements that we want our browser to use. So, for first name and last name those are just text inputs. But a lot of browsers now do email inputs and so we can use the email type. Now if your are user is using older browser that doesn't support the HTML5 input types this'll just be a text input, so it doesn't really matter. We're gonna have a homePhone, and this is going to be the tel or telephone field type. We also wanna have a cellPhone. Let's also have a birthday, right? And this is going to be the date, field type. You can also have a website, and this is going to be the url type, and finally, let's do address. And there's no type for address, so we'll just use text again. So, these are all the fields that we want our contact objects to have by default. Now, the beauty of this is our users don't have to fill in all of these. These can be saved to the database just as they are. In fact, the only two that we're going to make required are first name and last name. As long as the user fills in those, the rest of these will just be left blank. And that's okay. Now, if you look at our new form view right now, you can see we didn't actually use this contact object yet, and that's because we're gonna use it in the directives that we have yet to create. But one thing we did use here that we haven't created yet is this save function. So, let's go ahead and create that now. $scope.save. And the first thing we want to do inside save is to check to see if our new contact form here is valid. You'll recall that I said we have to name this form so that we can validate it. And validation is part of the reason why we're saving the types for all of these different fields. You remember I said, first name and last name will be required. Well, when our form is validated, if those fields have not been filled in, then the form will show as invalid. And we won't perform the save. Instead we'll show an error message. Same thing with a lot of these other things. So, for example if something is typed into the website box here, but it's not a proper URL, we'll tell the user to go back and fix that. And so, that's how we're gonna do validation. And so, the first thing we have to do in here is say, if scope.newContact, remember. That's the name of our form here newContact. It's scope.newContact.$invalid. Now if the form is invalid we're gonna have to do something that is a teeny little bit hacky here. We're gonna do scope.$broadcast. And we're gonna broadcast the message record:invalid. Now, the reason we're broadcasting this message is just for the first name and the last name fields. And you'll see how this makes more sense in the next screencast. But basically what happens is if the user goes to the new form page and they go right down and click save, the said form cannot save because first name and last name have not been filled in. And what we wanna do is highlight first name and last name in red. But unfortunately the way Angular works is that individual fields are immediately validated when you start typing into them. So if we start typing in a website URL, for example we go http, Angular will mark this red and say invalid URL right away because it is an invalid URL until you finish typing the full URL. And that's fine, that behavior will be acceptable, but it also means that it will not mark first name and last name is invalid unless someone were to say, type in their first name and then erase it. So, basically we need to touch that field for it to be validated. So we're broadcasting this message here so that from within those input elements, once we create them, we'll be able to capture this record:invalid message and mark them as invalid manually. You'll see how that works in the next screencast. However, if this is false, it means that our form is valid and we can go ahead and save it. So what we'll do is say $scope.contact.$save, and then underneath this, we can say, $location.url equals the home page. And actually, we want that to be contacts, not the home page. And this, of course, will take them back to their list of contacts where they'll be able to see the contact that they have just created. Now, unfortunately, there isn't a whole lot to show at this point in our building. If you look at our new contact form here, you can see I've got contact/new. We have the h2 and we have our button, but there's not really much of a form here. So, in the next screencast, we're going to begin building some really cool directives that will really bring a lot of functionality to our form.