 I like to start off these talks by telling you guys my password and I'd like to tell you guys one thing about myself that's true and one thing that's not true and you can guess which is which. It's just kind of a fun little icebreaker. So my two things are I'm wearing women's underwear and I'm proud of it. Okay, going right into the talk, the volume is like going wildly up and down but I think that's my fault. Okay, so what I'm talking about is the angular CLI like Pete said. And it's kind of a dual purpose talk I think because raise your hand if you mainly use angular one as opposed to two. And raise your hand if you mainly use two as opposed to one. So more people obviously familiar with one than two and not a lot of people using angular two in production yet just in general. So this will serve as an intro to the angular CLI and just kind of an intro to angular two also if you haven't used angular two yet. This is going to be a mostly live coding type deal as opposed to slides because I kind of hate slides. Okay, now having said I just said I hate slides, here's my slides. Who am I? I'm Jason Sweat. I'm a developer slash speaker slash trainer slash author. I wrote a book called Angular for Rails Developers although I'm not going to be talking about Rails at all today. I wrote a book about how to use angular and Rails together. I also have angularonrails.com which has just tutorials and stuff like that. I'm a panelist on the Ruby Rogues podcast. You might be familiar with the host Charles Max Wood. He has a lot of different podcasts under devchat.tv including JavaScript, Jabber and Adventures in Angular. So if you're not familiar with those two podcasts, those are really cool ways to find out what's happening in Angular, what's new. I usually will like go listen to at least part of a lot of the episodes and be like, okay, I didn't know about this new thing that's happening and then I'll go Google it and read about it that way. I also am the principal of Ben Franklin Labs which is just the company that I do business under individually. So I'm a consultant and I have some potential availability for a new client coming up in January. So if you have a need for some Angular help or Rails, talk to me tonight. So here's what we're going to do. Like I said, it's going to be mostly live coding and we're going to be building the beginnings of a CRUD app using Angular 2 and the Angular CLI. And if you have questions, don't wait until the end. Just interrupt me with your questions. I'd much prefer to answer your questions as we go when your question is pertinent to what I'm doing right now. So if you have a question, just blurt it out and I'll answer it right then and there. Okay. So what I've done that I didn't show you is going back and forth, the other CLI and that's the command that you run to install Angular CLI and then the executable is just called ng and you can see right now it's at 1.00 beta.20-4. That change is pretty frequently but it's not so volatile. If you've been working with Angular 2 like over this summer and then up until recently, it was kind of unstable when it was just in RC and you would build stuff and then it wouldn't work anymore because everything they did was not backwards compatible. I had to go update my book a billion times but now that Angular 2 is out, that part of it is pretty stable and Angular CLI, it hasn't fundamentally changed in a while. I don't expect it to fundamentally change going forward. So what is it? It's a way to generate code is one of the things that does it at least. You can generate components, let me actually go to the, oh I don't have it up. We can generate components, you can generate directives, classes, all that kind of stuff. It's super helpful. You can run tests with it and one really important thing you can do with it is you can actually spin up a new project with it. That's what I'm going to do. So I just typed in ng new and then my project name. This project I came up with is called Home Library. The idea is like you just keep track of the books on your shelf. I just came up with to have something to do a tutorial around. And the first thing that does is, oh wait, I'm not on the network which I will need to be in order to NPM install anything. So when you run ng new, it will create some files and directories and stuff like that and then it will launch into an NPM install which we know is downloading the internet. So that's going to take a pretty long time. Well that's doing that. Does anybody have any questions about anything before I move forward? Okay, nobody has any questions. Yeah, good question. I have no idea. It seems like pretty much everybody who is using Angular 2 has just decided that they're cool with TypeScript. And I don't think I've heard anybody ever, not even on all these podcasts and stuff like that. I've never heard anybody doing Angular 2 in anything but TypeScript, which is actually kind of surprising. Oh, and you know what Pete said reminded me of something? If you go to the Angular 2 website, they have a little tutorial that is, I think it's even an ES5, and you can kind of pick. You can pick I want the ES5 tutorial or I want the TypeScript tutorial. I don't know if they have anything in between those two, but there is that. So I guess if you're curious about using Angular 2 not with TypeScript, that might be a good starting point. Okay, so the NPM install is done. I'm actually going to adjust this mic so I can like do this. And then I'm going to CD into my home library directory. Okay, and the first thing we're going to do is we're going to make it our goal to show a page where we're showing a list of books. So let's say the end goal is to just write a crud application, just to teach ourselves how that works. Like how do I create a form where I can click save and have it actually save a record to a database on a server? How can I update a record? How can I delete something? Let's say that's our end goal, but to set some intermediary goals. Let's make our first one be the easiest one, which is can I just get a list of stuff from a server and show that on the page? So that'll be our first goal. And for that purpose, I do have this here. So at localhost 3000, I have a Rails app. And if I go to slash api slash books.json, I have a couple of books here in the database. Actually, this might even be, well, that's cool. Okay, so in order to do this, I'm going to first get a server going. Okay, so I just did npm start. And you can see after that super long first line, the next line just says ng serve. And you might also notice the web pack stuff. So Angular CLI uses web pack, and it just did a web pack build, and now it's serving it on port 4200. So we can go to port 4200 now, and we'll be able to see something. All right, so this is obviously super minimal, but that's exactly what we're supposed to be seeing, is just this app works thing. And I always like to pop open the console just to make sure that it's clean and there's no errors or anything like that. So this is exactly what we would expect. And before I even move on at all, let me show you what Angular CLI gave us in terms of directory structure and the files and all that kind of stuff. Okay, so at this root level, it's a lot of nuts and bolts type stuff, configuration and all that. And then in the SRC directory, this is stuff that's more closer to our app. You can see the app directory, the assets directory, and inside SRC app, that's where our actual application code will live. And when I generate a new component in a second, we'll see where it puts that. Who's familiar with Angular 2 components? Okay, few enough that it probably makes sense for me to describe what it is. So a component in my understanding, and I'm relatively new to Angular 2 myself, my background is in Angular 1 and then Rails also. But my understanding is that a component is a directive plus a template. And we'll see as we go some examples of this. So if we wanna get a list of, if you come back to this localhost 3000 slash api slash books.json, we wanna see a list of books. So how do we do that? First I'm gonna create a book list component. So you can see I use the ng generate command, that's what a lot of these things start with. ng generate component, and then the name like component, which is book list. You can see it created four things. A CSS file, an HTML file, a test, and then the actual component file itself. And let me just show you real quick. If you do ng test, it'll run your tests for you. And for the purposes of this demonstration, I'm not gonna worry about keeping the test suite passing the whole time, so this'll be the only time I do it. But it's just kinda neat that it can run your tests for you. And what I really appreciate about this is if you've ever worked on somebody else's Angular app, where it's maybe just, they don't have any tests or anything like that, and you have to retroactively add them, or even for a new project, it can be kinda time consuming to get everything talking to each other. So the fact that just right off the bat, you have this ready to go, and you don't have to do any configuration at all, I find that super helpful. And if you come into somebody else's project, if they're using Angular CLI also, then you know exactly how their system is gonna be set up. Cause right now a lot of stuff is like, each Angular project, at least in my experience, is like a unique snowflake as far as how it's structured and configured and all that kind of stuff. And I'm really hoping that if Angular CLI becomes like a standard part of most people's workflow in Angular 2, that Angular projects won't be so unique and you can come into any Angular 2 project and be productive relatively quickly because the Angular 2 projects aren't that much different from each other. So just wanted to touch on that real quick. We created that book list component, but if we come back here and refresh, nothing changed, cause we didn't add anything to this page. So let's do that. So this is the app component page. You get one component out of the box with Angular CLI, and you get this application component. And just to prove to you, I guess, that this is what it is, cause I would wanna know for certain that what I think I'm looking at is in fact what I'm looking at. We can see if we put some stuff there that it reflects on the page. So here's what we're gonna do. This is the book list component. And we can see inside this component annotation, there's a number of things. There's the template URL, which is probably kind of self-explanatory. There's the style URLs. Again, that's where you find the styles that apply to this directive. Then there's also selector. And that tells us what HTML selector we can use to invoke this component. In this case, it's app dash book dash list. So let's put that on app component HTML. And if we do it correctly, we should see it show up on that front page. By the way, this is booklistcomponent.html. It just says book list works. So this is what we should expect to see on that page. And in fact, that is what we see on this page. So pretty basic stuff so far. But this is a lot of stuff that's, even though it's basic, it's not always very obvious. It is. So now let's add an HTTP request that goes to this Rails app and get some actual data that we can show. But first, let's figure out why the heck this is doing this. I'm getting a 404, so let's see. Okay, I think the issue was that I moved my Rails app from one folder to another one, like right before I came here, which was dumb. But now I found the right place. So here's this list of three books that we have. What I would like is to get these three books showing up on this page. So how do we do that? This is the booklist component. And you can see that ngoninit function. If we put something in there, it'll do that thing when this component is initialized. And I'll just demonstrate that real quick. So we should see, there it is, in the console we see booklistcomponent initialized. So we know that if we put something in there, it's gonna get run. And what we wanna do is perform an HTTP request and that happens like this. Okay, so I like to stake things one tiny baby step at a time. So rather than try to go to the server and get the data and show it on the page, I'm just gonna try to get the data from the server and then console.logit and say, can I just do that much? And once I'm doing that much, then I'll go to the next step of actually sending it to the page. So this code probably looks pretty self-explanatory, this.http.get and then the URL of my endpoint. And then I have this subscribe. When I get the response, console.log the response. But this actually would not work because what is this.http? It doesn't exist. So we need to use Angular 2's, yeah, question? Good question. If you put it in the constructor, that's a great question. Let's just see what happens. It never occurred to me to try that, let's see. Okay, so apparently this is what happens. It doesn't like it when you do that. Which makes sense. Yeah, and I don't know exactly why that didn't work, but I would guess, oh, sure, yeah, yeah. So the question was, rather than put console.log and that ng on it, what if we just put it wherever inside the class definition? Would it execute it or what would happen? And what we found, as you saw, is it just blew up. And I don't know if that's because, so TypeScript is more strict about stuff than JavaScript. And so it could be because of that, I really don't know why it didn't work, but apparently if you try that, it does not work. That was actually a really great answer. Did anybody not hear that and want me to repeat it? Sure. So I'll just kind of summarize it if I can, although I probably won't say it as well as you did. A class definition isn't completely executable. The functions inside it are executable, but you can't just put code anywhere inside the class definition, because it's not like it's gonna execute that class definition from top to bottom. It's only gonna execute what's inside the functions. Is that a good, okay. Okay. So where we were was that we have this.http that I'm referring to, but it's not actually something that exists. So we have to get it via Angular 2's dependency injection. And Angular 2's dependency injection works a little differently than Angular 1's. So I'll just show you how it works. Okay. So we put this similar to how in Angular 1, when you have a function definition, you'll annotate it with the services or whatever you wanna inject into that function. This is similar, but a little bit different as you can see where we're defining this private member, HTTP. And if you're not familiar with TypeScript, when you declare a variable, you can add a colon and then after that colon, the type that that thing is supposed to be. So this thing we're calling HTTP, the lowercase HTTP, that is of type HTTP. And we could have called this anything. You know, we could have called that variable anything, but the HTTP part, that's significant because the type of it is that class called HTTP. But I am gonna call it HTTP. There's one more thing we need to add before we can expect this to work, which is that HTTP class, this file doesn't know anything about that yet. So we have to fix that with an import. Okay, now that we have all those pieces in place, we can expect it to work. Nothing ever works the first try, so I expect that this will fail. And it actually worked. You can see in the console, well you might not be able to actually read it, but you can probably tell that there's something there. And since I can read it, I can tell you that it is what it's supposed to be. It's that list of books. And since I'm such a fan of tiny baby steps, the tiny baby step I'm gonna take next is, instead of console.logging this raw response, I'm gonna take the JSON from the response and log that. Okay, so when this refreshes, again I don't know if you're in the back, you probably won't be able to actually, well you can see that that logs something different. Now it's just three objects. And if I expand that, now it's not just like that big long string, it's actually parsed out. So we wanna take this parsed out response, and here's what we wanna do. We wanna assign that to a member variable on that book list component class. And then in the template, we wanna refer to that variable. So here's how we do that. So on line 10 there, the books, colon any, I'm declaring a member variable called books, and the type of books can be anything. That's what the any means. And then in this subscribe, instead of just console.logging that response.json, I'm gonna say this.books equals response.json. Okay. And when this refreshes itself, we can see that there's no error. So if we did anything wrong, it wasn't anything that caused an error, but we don't really know that we did anything right either because there's no indication of success. So let's add something to the template. Let's do that. We're just putting books there. And there's something. This seems, this isn't obviously wrong. There's three objects there, but of course that's not exactly how we ultimately wanna output that. So I'll show you how we can output this in a way that makes more sense. Okay. So it's not a guarantee that I get this syntax exactly right, but apparently I did because now we see these three book titles. Yeah. Oh, sure. Sorry. Okay. So I'll just go over this. Okay. So we have a UL here. And then on that LI, it says ng4 equals let book of books. And there's some stuff behind what's happening here. Well, you can probably tell just by looking at it, even if you're not familiar with this Angular 2 syntax, that it's taking this array called books and it's labeling each individual book as book. And then for each one, we're outputting book.name. And that's all that I'm gonna say about that for right now because I don't remember all the details behind it, but there's a place in the documentation where you can read like that star ng4 is actually shorthand for something. So if you're interested, you can go look that up. Don't ask me because I don't remember. Okay. So we have this list of books. And now I think my next step would be, can I put a form on this page where I can type in the name of a book because that's the only attribute I'm giving a book right now. It has a name and that's it. Can I get to the point where I have a form where I can type in the name of the book and hit save and actually saves it to the database and then preferably updates this list. So let's do that. Pete, how are we doing on time? Okay. I'll just go for a couple more hours. Yeah, when there's one guy left, no, but I was thinking maybe 10 more minutes of stuff, 10 or 15. Okay, so I'm just committing what I did here. And before I go further, is there anything not that I know that I could even show it necessarily, but is there anything that people are particularly interested in seeing? That's a great question. We will come across that in part of what we're doing. So yeah. Okay, so the next goal is to get to a point. You know, just thinking about that end goal of a full CRUD app, which we're not gonna get nearly that far today. But thinking about that end goal of a CRUD app, what would the next baby step be? Well, ultimately, I would like to have a separate page where I can click a link and go to the new book page. And that's where the form is. And then after I save that new book, it takes me back to this list page and then shows me the new list, which includes the book I just created. But it's kind of a lot of stuff. That's more stuff than I tend to like to tackle in one go. So how about this? As the next goal, can I just get a form to show up right on this page? Then if I can get a form to show up in this page, can I click save and have it save something? Then if I can do that much, then I'll move that form onto a different page and deal with the routing stuff. So let's try that. And let me say something too. I'm gonna open up this book list component. Okay. So it's kind of a best practice in Angular to abstract away your HTTP requests into a service because you can get really cluttered if you don't. So I'm gonna create a service and I'm gonna move this into it. Okay. Now I can do ng generate service book. Now you remember before we did ng generate component, this is ng generate service now. This will generate something a little bit different. So before we had an HTML file, CSS file, TypeScript file and a test, here we just get a TypeScript file and a test. And obviously this is much, if you think back to what we got out of the box for that component when we generated it, this is a lot less stuff, which makes sense because the service is just like whatever you need it to be whereas a component has a more specific job. So I'm gonna open up the book list component. Then I'm gonna move some of that code into here. Okay. So one practice that I like to use is coding by wishful thinking, they call it. So I'm gonna write the code that I wish I had for this and I'm thinking it would be nice if I could do something like this instead. So that's the code that I wish I had. So let's make it so that code works. You can see that I'm doing this.bookService which there is no this.bookService yet and I'm doing this.bookService.getList. There's no such function called getList yet. I'm gonna create that function getList. Okay. And I'm gonna get a little audience involvement now. I'm referring to this.http in this service. Is that gonna work? If not, what do I need to do? I need to import HTTP, that's right. Like I can just copy that from the other place. What else? Right. Okay, and then here of course, I'm gonna take away HTTP. But you know, in order to get bookService to work, I probably should replace this HTTP with bookService. By the way, when you're doing these imports, you don't need the file extension. Okay, so can anybody see any problems with my bookList component? Does that look good? Looks good, okay. And I can see one problem with this. I'm missing the return. But other than that, any problems with this? Does this look good? Okay, let's see if it works. And it did not work. And here we touch on what you asked about a second ago is the providers. Says no provider for bookService. So here's what we have to do to fix that. In this annotation where we have selector, template URL, and style URLs, we have to add providers. And I believe that should make it work. It didn't. This.bookService.getList is not a function. Okay. If anybody caught this, they didn't bring it to my attention. We just put this return right in the constructor, which doesn't make any sense. I didn't do that as a trick. That was just a mistake. Okay, and now that works. We refactored our HTTP request into a service. And at this point, that might seem kind of pointless because now all we have is like more code that does the same thing. But as we go, and if we were to do more than we're just gonna do tonight, it would become more clear why this is beneficial. Sorry, you had another question? Why did I have to use a provider for bookService and not for HTTP? I was hoping nobody would ask that. I have no idea. Yeah. I have no idea. If anybody feels like Googling that, and if you find out the answer, let me know and then we can let everybody know. Because I really have no clue. Okay, now I'm just gonna commit this refactoring. What I'm gonna do next is I'm gonna put that form on here, get to the point where we can click save, and it saves something to the server, and I think that's all we're gonna do for today. Just get to that point. That'll take us a little bit to get there. So, how do we create a form in Angular 2? I'm gonna create a form component. And by the way, you don't have to do ng generate. You can actually just do ngg. And just like the other components, it gives us these four things. Okay, let's see if anybody knows this. If I wanna get this book form component to show up on this page, what would I need to do? If anybody is saying anything, it's too quiet for me to hear. I showed you guys earlier, so I think somebody probably knows. Exactly. And then where exactly would I put it? Yep. I could put it there or in the book list form, or in the book list component. It doesn't really matter, I guess. I'll put it in the app. Okay. And so if that worked, which I wouldn't see why it wouldn't, we would get book form works right there, which is of course, exactly what we see. So I'm gonna, I have this in part of my book, which I'm actually gonna just refer to, so I don't have to re-type it all. Okay, so I'm gonna go to the template for my book form component, and this is another self-explanatory part, but I have this form with a name label, an input type of text, and then a submit button. I'll just show you what that looks like. It looks exactly like you would expect it to look. And again, in the name of Baby Steps, when I click submit, whoops, let's just see if we can get something to happen. Let's console.log something when we click submit. Okay. So the directive syntax for Angular 2 is a little bit funny. Anything that's in event is in parentheses. Okay, so I'm calling this submit function. The ngsubmit thing, that's like a native Angular thing, but the submit, the part that I'm telling it to do when the form is submitted, that's just a function name that I made up that doesn't actually exist yet. So let's create it. Okay, so if this works as expected, when I click that submit button, it should console.log submit. And we have to put something in here, so let's put something in there so we don't get an error message. And I don't know if it's very visible, but we did in fact get a submit in the console when I clicked that. So that's great, that's what we expected. I'll ask the audience again, what do you think our next step should be in getting this form to actually save something to the server? Somebody must have an idea. It doesn't have to be very specific. Well, we have this submit function in the component. I think exactly. We wanna add an HTTP request to save it. So we could go about this two ways, I guess. I don't know why I didn't raise this up a long time ago. We could go about this two ways. One way is we could inject HTTP into book form component and then afterward refactor it into the service, or we could just start by having it in the service and not have to refactor it. I'd rather do the second way. So we'll do that. First step is to put something in the submit function. And again, I'll just make up something that doesn't exist yet, coding my wishful thinking. I'll make something that doesn't exist yet and then make that code work. Okay, this.bookservice.save. There's no save function that we automatically get on the book service. I just made that up just now, and now we're gonna make it work. And we're probably gonna pass something to it, but I don't even know yet what would we pass to it. And in fact, let's take care of that part first because it'll be a little bit easier to make this service call work if we know what we're gonna pass to it. We have to give it the value that we're saving, right? So here's how we do that. Kind of like on the book list component, we gave it a member variable that held the list of books. In this case, we're gonna give it a member variable that holds whatever book we're creating. So it's gonna be like a book class that's empty at first. And then when you type something into here, it will assign whatever you type. It'll assign that to the name property of the book class. But right now we don't even have a book class. So as you might imagine, we can use an Angular CLI to generate a book class. And again, this one is a lot simpler than a component. We just get this typescript file. And since it has a name property, I'm gonna add a constructor that gives it a name property. Then I'm gonna import this book class into my book form component. And I'm gonna say this, I'm gonna say model equals new book. And since I added that name property to the book class's constructor, we have to give it something. So I'm just giving it something right now to give it something. Then if we go to this template and add an ngmodel here, we should see that name I just put in foo. We should see that appear in the form. Okay, and I didn't even know if I did that right. No, I didn't. I think here's what I did wrong. That's still not right. Luckily I have this backup here that can tell me exactly how to do it right. Okay, ngmodel equals model.name is what I need to have. I'm just gonna copy and paste this so I don't make any mistakes typing it. That looks pretty much identical to what I already had, just a different order. No, it's not that. This is what makes live coding exciting. You have the possibility of just completely crashing and burning, which I'm not gonna do. Okay, so let's see what else could be wrong. So if it's not the ngmodel part that's wrong, then maybe it's something in the book form component. So let's see if there's something in here. So model equals new book, some book. Yes, I'm doing about the same thing there. It's very interesting. Book form component. Okay, let's try something else. If I can't get it to, yeah. Well, I did a hard refresh and that didn't do it, but here's what my next idea was. If I can't get it into an ngmodel, let people are leaving now because I'm messing up. If I can't get it into an ngmodel, can I at least assign some property to this class and get that to show up somewhere on the page? Okay, so I have a property, I'm just calling foo and I'm assigning it to bar. Okay, so I want to make it really obvious for myself, here's what foo is. Okay, and foo is in fact bar. That's very interesting. Okay, so now I'm just gonna copy this whole entire form because maybe I somehow, when I re-typed this form, maybe somehow I did it wrong. Well, it's a difference, but I doubt that it's the difference because here I just happen to call it something differently, something different, so let me do that. Okay, yeah, so that was a difference, but it wasn't the difference. Could be, that's a good thing to check, let's check it. Okay, aha, I think that's gonna be it, Pete. Do you guys see what it is? This constructor doesn't have any braces after it. Okay, Pete, you're like two for two on helping me out with stuff here. Okay, so that worked, that's great. Now, when we click submit, let's have it, before we try to make the HTTP request, let's just have it console.log something first just to make sure that the thing that we want to pass to the server, it is what we think it is. Okay, so when we click submit, should console.log something. Yep, and in case you can't see it, it just says book with a property name and a value of foo, which is exactly what we'd expect. So now instead of just this.bookservice.save with no arguments, I'm gonna put this.model, but now we have to make a save function on book service actually exist. And what goes in here, for some reason, a save in Angular 2 is like way more involved than just a get. So I'm gonna copy and paste that from my book. Okay, so the thing that I'm passing to save is an instance of the book class. And I'm doing all this stuff, I'm creating a body on line 15, a body, I'm JSON.stringifying my book. I'm setting some headers, I'm setting these request options. Don't ask me what any of that stuff really means, I don't know, but then on line 19, I'm doing this.http.post to apibooks.json. And I actually need to change one thing, because I'm doing things a little bit differently in this case, and in my book, I need to specify the full URL. And then lastly, this actually won't work unless I do something with the response. So let me do that. Okay, and if this works as expected, I'm gonna be done, and then we'll take any, yeah, question? Ooh, good catch. Okay, and obviously I could go much further than this, but if this works as expected, I'm just gonna be done here and then answer any final questions if there are any. By the way, the way that we'll prove to ourselves that it worked, well, I guess we don't have to go here. The way we'll prove to ourselves that it worked is we'll just refresh this page and see this new book here. So let's see if it worked. Okay, and like I said earlier, nothing ever works first try, so why didn't it work? Hopefully all this error message just immediately disappears so we can't read it, so that's awesome. So let's see if we can figure out what went wrong. I think I know, but does anybody want to chime in with a guess? I don't think it's book, but what about headers and request options? This file doesn't know anything about those classes, so we have to, in this case, we don't have to inject them or we don't wanna inject them because with something like when we create a member, like book as a member, then bad example. When we have like a book service as a member of a component class, then we inject it because we wanna do like this.bookservice.whatever, but since we're not, we don't have an instance of this that's like this.header, you know, we're just using it like this so we don't need to inject it, but we do need to import it. So here, instead of just importing HTTP, we're doing HTTP headers and request options from Angular HTTP. And I have a hunch it's still not gonna completely work, there might be something else we need to fix too, but let's see what happens. Okay, it still doesn't work, so let's see what else could be wrong. It's not headers or request options anymore. I'm just gonna refer back to my cheat sheet here to see what else it might be. I'm just gonna copy this whole entire file and see if there's anything I did wrong. URL, oh okay, okay, so the URL issue is fixed. Still getting that same thing. Oh, good idea, good idea. Yeah, yeah, yeah. I don't know why I didn't think of that. Okay. Cannot read, oh, okay, so now it's obvious. Cannot read property save of undefined. What does that mean we forgot to do? What are we calling save on? We factored everything from the component out into a service. So what are we calling save on? Book service. Did we inject book service into book form component? No, we didn't. And I'm just gonna go to book list component where we've already done this and copy this line. Okay. I think we could reasonably expect that to potentially work. And we still forgot at least one more thing, no provider for book service. Okay. Who thinks it's gonna work now? I'm disappointed in you guys that so few of you, believe in me, okay. So I'm gonna click submit and it worked. All you guys who thought it wasn't gonna work were wrong. Okay. And then if we refresh this page, we should see a fourth book now called Foo. Thank you. Any final questions before I depart from the stage? What happens instead of you? Okay, so the question is what happens if you have interfaces instead of a class? I have no idea. Yeah, and I'm just, because what Pete said there was pretty spot on. Pete, you should just follow me to all my presentations and just when somebody asks a question, just you answer instead of me. But the deal is with an interface, you can't instantiate that directly. An interface is just kind of a pattern from which you can define a class and then you can instantiate that, I think is what you were saying. So yeah, and if you wanted to do something like that, I'm not sure what the use case for that would be. Any other questions before we conclude? Yeah, it's a good question. So having experience with Angular 1, how do I feel about all the changes in Angular 2? It's kind of interesting because Angular 2 is like so radically different from Angular 1. And people have complained with major Rails versions that they're not backward compatible and David Heinemeyer Hansen's response to that is like, well, we wanna do what's right and what's technically sound going forward and make that our main consideration rather than consider what's gonna be backward compatible. And I can understand that form of reasoning. And it seems like what the Angular team wanted to do was they said, okay, we created Angular 1, we made some design mistakes and some things are kind of like overly complex or hard to understand. So in Angular 2, they wanted there to be fewer concepts, simpler, easier to understand. And so I think they had, they were more asking the question like, if we're just starting from a clean slate, how could we design something really nice to use? And they were taking that as their main consideration as opposed to like what was gonna be backward compatible. That's just my guess. And looking at it through that lens, like I think it makes sense. But obviously there's the challenge of like, now I have to either upgrade my Angular 1 apps to Angular 2 and it's like, how do you accomplish that? Because that's not a very, it's not like you just install Angular 2 and you're good to go. There's a lot that would need to change. And I think a lot of people's response and the app that I work on like all day, every day right now it's Angular 1, we have no plans to upgrade it to Angular 2 anytime in the foreseeable future. And I think that's the way it's gonna be for a lot of people probably. And so just for me as a developer, I'm gonna do any new stuff in Angular 2 probably and just leave the Angular 1 stuff behind. Great question. So I could talk for a long time about deployment but I'll just say one thing real quick. When I was running the server process, that was ng serve that was making that localhost 4200. When I deployed to production, okay so when you do an ng serve, it does an ng build before that and you can run an ng build anytime you want and it'll create your JavaScript files, it'll do your translation and all that stuff. When I do a deployment, I set it up, I use Heroku. So I set it up so that after it deploys to Heroku, it triggers an ng build and then just serves static files on Heroku. So that's kind of the short answer but if you wanna talk more about that there's tons of nuances within it too. Okay, maybe this is the last one, one more question? That's a great question. So there is a router for Angular 2 and if you've been using Angular for the last several months when they've been getting ready for Angular 2, that was like one of the most tumultuous parts of it that changed so much but now it seems pretty stable. I didn't get into that just now because I really wanted to limit the number of things that I touched on because if I was trying, I had a hard enough time creating this app that I've already created before without introducing that kind of stuff so I just wanted to keep the concepts to as few as possible but yeah, that definitely exists. Okay and with that I will turn it back to Pete for any closing remarks and I just wanna say again that reminder of that potential client opening in January if you need any help with Angular 2, Angular 1 or Ruby on Rails is something I also do. Just come talk to me after this.