This course has been updated! We now recommend you take the Angular 9 Fundamentals course.
Transcript from the "Creating a Service" Lesson
[00:00:00]
>> Lukas Ruebbelke: So we just talked about routing and we saw, in a very interesting, roundabout way, how to do lazy loading in routing. So now, we're seeing how to compose or navigate across components. So this is, I think of kind of a horizontal kind of construction as you're assembling things horizontally based on a route table.
[00:00:24] So this route goes here, this route goes here, and so I think of this as horizontal. Now, in our project component, we have this data structure here, projects, that right now is local to this component. So obviously, this is not going to scale, the question is what happens if the home component is the project or something else?
[00:00:52] And so what I want to talk about is services, how to create them, how to consume them. And then we'll just go right into communicating with a REST endpoint. So, now that we have this kind of project components here, let's go ahead and abstract out the data structure that we put in line.
[00:01:19] Let's move it to a service and start to kind of iterate on that, to make this better. So the first thing that we're going to do is, let's generate a project service. So in our command line, ng g s for service and we'll go features, and so what I'm doing here is I'm going features/.
[00:01:46] So I'm saying in wherever I generate this, I want this to be in a feature's folder. So Francis will generate or I'll generate an interface for the projects as well. So actually that features as projects/projects. And then let's go, project=core-data and let's give this is a d for dry run and see what happens.
[00:02:17] All right, so you can see here. lib/projects/projects service, as so. So let's go ahead and take the flag off. Now what I'm also going to do, since we're here, is I'm going to generate an interface. So ng g i for interface, we're going to go projects and because this is an interface for a single project, we are going to leave the singular, and we'll go project=core-data.
[00:02:55]
>> Lukas Ruebbelke: There we go. All right, so now let's go ahead, and I'm gonna just put this down for a second. Let's pick up this structure and well, we'll leave it here for a second. But let's navigate to our project service.
>> Lukas Ruebbelke: And so, I kind of hopped right to it.
[00:03:25] But if anybody's wondering where that is at, it's in core-data, lib, projects, projects service. And then what we can do is let's go, and we'll go private. And so this is a compile time, it'll check this. But at runtime, there's really no concept in essentially private or public.
[00:03:48] But nonetheless, I think it's good for indicating intent is that I would prefer that people not access this directly, but instead, let's create an all method that just returns the stopped projects.
>> Lukas Ruebbelke: And that's not, there we go. Stopped projects and let's also,
>> Lukas Ruebbelke: I'm going to copy the guts of one of these objects and let's go into project.ts and let's define this interface.
[00:04:34]
>> Lukas Ruebbelke: So we'll do id as a string.
>> Lukas Ruebbelke: Actually, most of these are going to be a string.
>> Lukas Ruebbelke: details,
>> Lukas Ruebbelke: Just because it says string, doesn't mean it is a string. We'll go number, and we'll go Boolean.
>> Lukas Ruebbelke: And so, now we're saying any project object that we reference in the application, it needs to appear to this interface, which allows us to do this.
[00:05:22]
>> Lukas Ruebbelke: One, is we can strongly type this so we can say this is a project, or rather an array of projects. And so notice that I need to import this here. You can also do it as a generic, so you could go like this. For some reason, VS Code thinks every time I do a generic, that that's an HTML tag.
[00:05:47] Whatever, I personally, for me, for this form, you can also go here. And you can say when I call all, that I'm going to get an array of projects.
>> Lukas Ruebbelke: And so we know what's coming out of it. And specifically, we can click in here, and you can see this.
[00:06:07] So this is a really nice way of indicating not only to your IDE, but other developers, like this is what this thing is, and this is what you can expect from it. And so in our,
>> Lukas Ruebbelke: CoreDataModule.
>> Lukas Ruebbelke: Let's go ahead and,
>> Lukas Ruebbelke: We'll wire this up. First things first, let's go here.
[00:06:38]
>> Lukas Ruebbelke: And CoreDataModule, and then we'll go,
>> Lukas Ruebbelke: ProjectsService.
>> Lukas Ruebbelke: Then we'll do just,
>> Lukas Ruebbelke: One thing you wanna avoid as well is for circular reference. You can see here, it's wanting to import from workshop core-data while we're in workshop core-data. And so, VS Code doesn't really have a good way of knowing that, and so if you're in a particular, kind of like a scoped space.
[00:07:24] Then, it's really helpful to just pay attention to where this is coming from, and work within that particular,
>> Lukas Ruebbelke: Kind of playground if you will.
>> Lukas Ruebbelke: Here we go, so let's clean this up.
>> Lukas Ruebbelke: Then I'll tap back into our CoreDataModule. And we will set this up as our providers.
[00:08:19] And within here, we are going to define our ProjectsService, like so.
>> Lukas Ruebbelke: After getting bit on the route example, I'm super paranoid about getting this just right or it'll fall apart. All right, so now that we have our module that has a ProjectsService, or it's registered as a provider.
[00:08:56] Let's go into our project component, and let's declare this, but we're not going to do anything with it just yet. So when you have a service, and you need to get it into a component, or anywhere else. You can use dependency injection, so you pass it in via a parameter to the constructor.
[00:09:27] So I'll go ProjectsService.
>> Lukas Ruebbelke: There we go.
>> Lukas Ruebbelke: See what this is angry about.
>> Lukas Ruebbelke: Okay, and so now that we have injected this It is available for us to use elsewhere with a caveat. So one of the things with TypeScript that happens, that does not happen in ES6 is this idea of constructor assignment.
[00:10:14] So if you've done the ES6, what you would have to do is something like this.projectsService and then inject this.
>> Lukas Ruebbelke: And then when this comes in, and then go this.projectsService. And so when I do angular jest in ES6, this is basically what I have to do is take a parameter because scope to that function and then assign a local member so that it is available.
[00:10:49] With TypeScript, what it would do is if you add it in public or private so essentially an access modified. It will go ahead and say, clearly this needs to be a part or a member of this class. Because you're saying I want to modify the accessibility of this.
[00:11:10] So public, private, what this does is under the hood it just takes this and assigns that to a local member. So what you can do now is, we can go here, and let's say getProjects().
>> Lukas Ruebbelke: And we'll go this.projects = this, and noticed it picked it right up.
[00:11:37]
>> Lukas Ruebbelke: Now what I wonder is if I took off this modifier. Notice here, it's like I don't know where this is because it's just now just a method or a parameter to a function and that's it. But the minute and this is a little bit of TypeScript magic, the minute you go like this, then it's like I don't know what that is, hooray.
[00:11:58] So,
>> Lukas Ruebbelke: We have this method, getProjects, now we need to call it, how do we do that? So I held off talking about this in the components piece, because I wanted to talk about it in the context of what an asynchronous frame.
>> Lukas Ruebbelke: When you have a component that is relying on data, that is potentially asynchronous.
[00:12:31] When your component is initialized, if you do something like this.localValue = this.remoteValue per se. Like remote asynch value.
>> Lukas Ruebbelke: This is just pseudocode. When is the constructor fire?
>> Lukas Ruebbelke: Just the second you instantiate a class, it's immediate. And so, you may reference something locally that doesn't exist yet.
[00:13:06] Because there's an asynchronous operation happening that's going to fetch that for you. And so angular has exposed various life-cycle hooks of a component such as being added to the stage, being initialized, being taken off the stage. So that when certain things happen in your application, you can then respond to that efficiently.
[00:13:31] So this is actually a really good way to optimize your application, and so you can for instance, do interesting things like turn off certain bindings. And then manually within your lifestyle hooks, manually kind of update those things and be very efficient. So Leonardo has a pretty good talk, he did it ng-vikings a few years ago, where they were able to massively improve the performance of their application by delegating a lot of the heavy lifting in a component life-cycle hooks and not using the default binding.
[00:14:10] So in this case, ngOnInit is fired when basically all of the data or all of the bindings for a component has been satisfied. So kinda the default is, this is the safest place to put something. And so from here, ngOnInit will go getProjects. We'll save this, what we'll also do is just go ahead and just scope these out.
[00:14:35] This is a Project.
>> Lukas Ruebbelke: VS Code has failed me, there we go. And we'll set this to a Project as well.
>> Lukas Ruebbelke: Still good. Let's see,
>> Lukas Ruebbelke: At least it's rendering. Let's double check. All right, I have to be super certain.
>> Speaker 2: You had some red squiggles on the end.
[00:15:19]
>> Lukas Ruebbelke: That is,
>> Lukas Ruebbelke: I really dig VS Code but I guess some false positives sometimes. So I may wanna take a break. I actually bet if I stop and restarted it, some of those things would go away. So we're definitely pulling from the remote server. Well, not the remote, the remote service.