Most of the blogs are related to ruby and rails developer problems.
Injecting services in angular 2
Get link
Facebook
X
Pinterest
Email
Other Apps
-
Angular 2 applications can basically be written in any language, as
long as it compiles to JavaScript in some way. When writing our
application in TypeScript, we use decorators to add metadata to our
code. Sometimes, we can even omit some decorators and simply rely on
type annotations. However, it turns out that, when it comes to DI, we
might run into unexpected behaviour when injecting dependencies into
services.
This article discusses what this unexpected problem is, why it exists and how it can be solved.
Injecting Service Dependencies
Let’s say we have a simple Angular 2 component which has a DataService dependency. It could look something like this:
@Component({selector:'my-app',template:`<ul><li*ngFor="let item of items">{{item.name}}</li>
</ul>
`})classAppComponent{items:Array<any>;constructor(dataService:DataService){this.items=dataService.getItems();}}
DataService on the other hand
is a simple class (because that’s what a service in Angular 2 is), that
provides a method to return some items.
Of course, in order to actually be able to ask for something of type DataService, we have to add a provider for our injector. We can do that by passing a provider to bootstrap() when bootstrapping our app.
bootstrap(AppComponent,[DataService]);
Until now there’s nothing new here.
So where is the problem? Well, the problem occurs as soon as we try
to inject a dependency into our service. We could for example use Http in our DataService to fetch our data from a remote server. Let’s quickly do that. First, we need providers for the injector, so it knows about Http.
Angular’s http module exposes HTTP_PROVIDERS, which has all the providers we need to hook up some http action in our service. Next, we need to inject an instance of Http in our service to actually use it.
Boom. This thing is going to explode. As soon as we run this code in the browser, we’ll get the following error:
Cannot resolve all parameters for DataService(?). Make sure they all have valid type or annotations.
It basically says that it can’t resolve the Http dependency of DataService
because Angular doesn’t know the type and therefore, no provider that
can be used to resolve the dependency. Uhm.. wait what? Didn’t we put
the type in the constructor?
Yea, we did. Unfortunately it turns out this is not enough. However, obviously it does work when we inject DataService in our AppComponent.
So what’s the problem here? Let’s take a step back and recap real quick
where the metadata, that Angular’s DI need, comes from.
If we take our AppComponent, once decorated and transpiled, it looks something like this (simplified):
We can clearly see that AppComponent is decorated with Component, View, and some additional metadata for paramtypes. The paramtypes metadata is the one that is needed by Angular’s DI to figure out, for what type it has to return an instance.
This looks good. Let’s take a look at the transpiled DataService and see what’s going on there (also simplified).
Oops. Apparently we don’t have any metadata at all here. Why is that?
TypeScript generates metadata when the emitDecoratorMetadata
option is set. However, that doesn’t mean that it generates metadata
blindly for each and every class or method of our code. TypeScript only
generates metadata for a class, method, property or method/constructor
parameter when a decorator is actually attached to that particular code.
Otherwise, a huge amount of unused metadata code would be generated,
which not only affects file size, but it’d also have an impact on our
application runtime.
That’s also why the metadata is generated for AppComponent, but not for DataService. Our AppComponentdoes have decorators, otherwhise it’s not a component.
Enforcing Metadata Generation
So how can we enforce TypeScript to emit metadata for us accordingly?
One thing we could do, is to use DI decorators provided by the
framework. As we learned in our other articles on DI, the @Inject decorator is used to ask for a dependency of a certain type.
We could change our DataService to something like this:
Problem solved. In fact, this is exactly what @Inject
is for when not transpiling with TypeScript. If we take a look at the
transpiled code now, we see that all the needed metadata is generated
(yeap simplified).
However, now we have this Angular machinery in our code and
unfortunately, we won’t entirely get rid of it. We can do a little bit
better though. Remember that we said metadata is generated, if
decorators are attached to our code?
We can basically put any decorator on our code, as
long as it’s either attached to the class declaration, or to the
constructor parameter. In other words, we could remove @Inject
again and use something else that we put on the class, because that
will cause TypeScript to emit metadata for the constructor parameters
too.
Of course, putting just anything that is a decorator on a class
doesn’t sound really appropiate. Luckily, Angular comes with yet another
decorator we can use. @Injectable
is normally used for Dart metadata generation. It doesn’t have any
special meaning in TypeScript-land, however, it turns out to be a
perfect fit for our use case. We don’t have to build a new one
ourselves, and the name also kind of makes sense.
All we have to do is to import it and put it on our DataService like this:
Again, this will just enforce TypeScript to emit the needed metadata,
the decorator itself doesn’t have any special meaning here. This seems
to be currently the best option we have to solve the illustrated
problem.
When you complete the free trial form you will get a screen like this: click whatever the linux version you do have then it will install the .run file. Linux– In the folder where you downloaded the Linux package, run the commands below for your platform. Then, follow the wizard instructions. 64-bit Linux Systems sudo chmod +x WowzaStreamingEngine-4.4.0-linux-x64-installer.run sudo ./WowzaStreamingEngine-4.4.0-linux-x64-installer.run 32-bit Linux Systems sudo chmod +x WowzaStreamingEngine-4.4.0-linux-installer.run sudo ./WowzaStreamingEngine-4.4.0-linux-installer.run If you acquired a new license key, you'll find it in the email that you received from Wowza Sales. To create a user name and password for an Administrator account. You'll use this account to sign in to the browser-based Wowza Streaming Engine Manager. The user name and password values are case-sensitive. Linux – /usr/local/WowzaStreamingEngine-4.4.0/ (as the root user) Starting and Stopping ...
In highcharts may be some time you need subcategories of a category or more deep nested categories for that you need to use a js file called grouped-categories.js it is a plugin provided by highcharts for grouped categories. this plugin can be downloaded from https://github.com/blacklabel/grouped_categories/ after download please refer to the home page for examples http://www.highcharts.com/plugin-registry/single/11/Grouped-Categories but even though I followed there documentation but I haven't found it easy for me to implement it in column range chart <div id="container" style="width: 100%; height: 100%;"></div> <script src =''> </script> var chart = new Highcharts.Chart({ chart: { renderTo: "container", ...
I’ve been writing this web app that has the following models: Order, Recipient, Message. An order has many recipients and a recipient has many messages. The recipients are also dependent upon the order and the messages are dependent upon the recipient. In Ruby code this looks like: Order.rb class Order < ActiveRecord::Base has_many :recipients, :dependent => :destroy has_many :messages, :through => :recipients end Recipient.rb class Recipient < ActiveRecord::Base belongs_to :order has_many :messages, :dependent => :destroy end The idea here is that when I delete an order, I also delete any associated recipients and any associated messages. My controller looked like this: def delete Order.delete(params[:id]) end There are a couple things wrong with this. The first and most important thing is that when I delete a row in the order table, it leaves orphaned rows in the order and messages table. I want to delete these rows as well...
Comments
Post a Comment