This course has been updated! We now recommend you take the Angular 9 Fundamentals course.
Transcript from the "Creating Services" Lesson
[00:00:03]
>> Lukas Ruebbelke: So, we've talked about components, we've talked about templates and hopefully by now we can kind of see how the kinda fit together. A component is just a JavaScript class that contains all of the imperative logic and our templates are even more so than ever just HTML. That we're binding to native dom events, attributes, properties, etc., and that we're using that metadata to kind of bind these things together.
[00:00:36] Or rather take, Angular takes the metadata and says, take this class, take this template and put them together. So this is kind of what dollar compile was doing in Angular1 but you still have that resemblance of the template controller pair from Angular1. It's just more clearly defined and I think greatly simplified.
[00:00:55] Also, kind of the natural extension of that is what happens when we need to actually do something fairly non trivial from within the component that it doesn't belong there. For keeping our components light and focused. More so the use case comes up as what happens if I have functionality that I need to share in more than one component.
[00:01:18] Well, the answer is you basically promote that functionality into a service. And so this may come as no surprise that a service is just a class. Scandalous, I know. So similar to components, again, just a class. And we define our service API by creating methods directly on that class.
[00:01:48] And we can also expose public properties- again this is more so for compiled time, notifications, I-D-E stuff, but. You can indicate like hey this is private, there is public. There is that notion of that. So just the class, we have the state service, we have this private variable called _message and We now have some getters and setters to use that.
[00:02:20] You'll notice that I am using an underscore in this case. I don't actually have a strong opinion on that. I kind of go back and forth of do you indicate it that it's private? Do you use underscore? You know there's different kind of naming conventions that you'll see depending on where you are.
[00:02:36] And for me personally, I don't have strong opinions. For instance with observables, you'll see a lot of times a dollar sign at the end of the variable to indicate that this is a stream or a stream of money as I like to think of it. And so that's why you have a dollar sign.
[00:02:52] But, this is pretty, anybody from kind of a classical background, they can look at this and it's pretty obvious what's happening. How do we make this available to Angular to use? This is where our Injectable metadata comes in. Just like the component metadata, we decorate our service with @Injectable to make our class, to mark it as being available to the Injector for creation.
[00:03:24] Now we'll throw a NoAnnotationError if you try to basically inject something that you have not marked for injection, which I've done that a few times. So in this case, real simple, you write your class, you define your API on it. Like this is what I want this thing to do, and from there you import the injectable module, and then you decorate it.
[00:03:51] Any questions so far? I think that by now, I almost feel silly just kind of reiterating this, but class, import, decorate. Pretty straightforward. And, so this is where, once you start to build these out, it's like, I'm doing the same thing like over and over and over. And so, injecting a service, we've actually seen this a bit.
[00:04:13] But it's as simple as importing the service class and then defining it as a parameter on the consumer's constructor. We can inject services into other services, it's the same exact way. And there can only be one instance. So this is something that Is quite different from Angular 1 that I had to read a few times to really kinda wrap my mind around it.
[00:04:43] In Angular 1 there was one injector for the entire application. And so any time you needed a service it would go and look in the service factory or the service cache. Does this exist? If not, it would instantiate it from the service factory and then store that instance to be use across the entire application.
[00:05:03] So it was one instance per injector. So, the difference is with angular two is you can have multiple injectors and this is where, again, it gets interesting with hierarchical dependency injection that you can now have multiple injectors operating in various levels in your application and so that every component can have its own injector, if you will.
[00:05:32] So they may share injector, so this kind of stuff under the hood, that the documents are not real clear about. But, it's very possible. It's actually almost a given that at various levels, you will have different injectors. And therefore, you will have different instances of that service. So it's still one service per injector.
[00:05:54] The difference is now, you have multiple injectors. And so from here, I'm importing the state service from our common state service module. And then, in our constructor, I'm marking this as private. And I'm just injecting this in and from here I can go this_stateservice. And call a method on this.
[00:06:20] So we've seen this a few times today. And I don't have a slide for this but one thing I want to call out is if you need something to be available, such as your routing providers, that's a good example. Then you simply need to go in injected at the top level component or if you need something essentially at some level to be available higher.
[00:06:44] Then you can just keep promoting that up, but just know that when you inject something it's only available for that component and it's children. So the way you get around that is that you need to ensure that it's single instance is available for the entire application injected when you bootstrap your application.
[00:07:01] And let me show you what that looks like. In our boot file here, router providers is a really good example of something that we would want to be available for everything cuz routing is kind of a global affair. And so we're doing this here. Whereas with the home component, we are just injecting this in directly.
[00:07:33] And you can inject it in multiple places, but in this case I probably would not because it's not really a global concern, is I would inject the state service at the top level and then let it manage everything. So do try to keep that on a per component basis and really be cognizant of that.
[00:07:56]
>> Lukas Ruebbelke: Another good example of something you would put into here is that once we get into NGRX, which kind of adheres to a redux pattern of a single state tree. So now your entire application goes into this single state tree object. Obviously you would want that to be available at the top most part of your application.
[00:08:18] And from there, the API is, and I don't have this imported into this application, but you would say, hey, I need to essentially create these reduct style stores. Here it makes this available. So if anybody wants to preemptively start to look at that, if you go to GitHub/NGRX/store you can see kind of that example but obviously your entire application state you would want to be at the top level.
[00:08:55] Let me see what the challenges are. That was refreshingly concise and to the point. I am impressed. I was anti Scott Moss. I said that in love bro, all right.