Doge Doge - 2 months ago 9
AngularJS Question

Injecting window object into a component into AngularJS with DI

I'm loading socket.io in my application like so:

index.html
<script src="http://myapp.com/socket.io/socket.io.js"></script>
...
// Angular stuff


I have a component called
Socket
which requires
window.io
to work.

import { Injectable } from '@angular/core';
import { Events } from 'ionic-angular';

@Injectable()
export class Socket {

public isConnected: boolean = false;

constructor(public events: Events) {
if (typeof window.io === "undefined") {
throw new Error("Socket.io is undefined.");
}

this.io = window.io;
}

connect() {
this.io.connect("...");
}

listen() {

}

}


In theory, it may work (didn't test) but it is not a good practice to inject stuff from window scope into classes.

Is there any way to do it like this:

import { SocketIODriver } from 'socket.io';
import { Socket } from 'App/Socket/Socket';

@Component({
templateUrl: 'layout.html'
})
export class ConferenceApp {
constructor(
public io: io,
public Socket: Socket
) {
this.socket = new Socket(new SocketIODriver());
}
}


Thank you.

Ps. IIRC, socket.io has to be loaded from the server, that's why I load it from my server. If it can be placed into my JS folder, that would be even better.

Answer

Angular 2 works with injectors. Each injector can be used such a way you can use them easily.

For example, looking at the angular 2 injector API, you can use an object called { useValue : 'theValueToInject' }.

This way, when you want to inject something that is already instanciated, or is just a value (aka window object for example) you can pass it to the injector of your module through useValue :

@NgModule({
  declarations: [
    ...
  ],
  imports: [
    ...
  ],
  providers: [
    { provide: 'Window', useValue: window }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

And so, you can use it like :

constructor( @Inject('Window') private window: any) {} // or window type, I don't know what it's exaclty
Comments