I'm trying to use dependancy injection in angular using an injector. I want to me able to instantiate types at runtime depending on what this component is sent.
#Injectable()
export class ServiceInjectionManager {
private _injector: ReflectiveInjector;
constructor() {
this._injector = ReflectiveInjector.resolveAndCreate([
MockBackend,
BaseRequestOptions,
{
provide: Http,
useFactory: (backendInstance: MockBackend, defaultOptions: BaseRequestOptions) => {
return new Http(backendInstance, defaultOptions);
},
deps: [MockBackend, BaseRequestOptions]
},
AppSettings,
HierarchyService
]);
}
public resolve<T extends HierarchyService>(type:any): T {
return this._injector.get(type);
}
}
I can't seem to find a way to pass a type. I have taken multiple approaches including:
public resolve<T extends HierarchyService>(T): T {
return this._injector.get(T);
}
It seems that generics in TypeScript are not the same as in .NET.
Related
I have a search bar in app.component.ts that has an input value.
results.component.ts is embedded with a router-outlet in app.component.html
When results.component.ts is the current activated route, the search works fine and so do the results.
However, if someone clicks on a result, results.component.ts is replaced with a different component view detail.component.ts (it provides them with more information about the result.)
On detail.component.ts I have a "back to results" link setup with a routerLink='/'. And mind you, the search query is still present in the search bar because that view never gets replaced.
When this back button is clicked, results.component.ts reloads and fires ngOnInit.
The problem: I can't access the value of the search string in app.component.ts from results.component.ts ngOnInit to repopulate the results. I've tried almost everything I can think of.
I already have a service built, but I don't know how to set it up to communicate that value, if that is the solution.
Updated with code
app.component.html
//other html
<input placeholder="What do you want to learn?" name="searchStr" [(ngModel)]="searchStr" (keyup.enter)="searchCourse($event)">
interaction-service.service.ts:
import { Injectable } from '#angular/core';
import { Subject } from 'rxjs/Subject';
#Injectable()
export class InteractionService {
// Observable string sources
private searchStr = new Subject<string>();
// Observable string streams
searchStr$ = this.searchStr.asObservable();
sendString(searchString: string) {
this.searchStr.next(searchString);
}
}
app.component.ts:
//other imports
import {InteractionService} from './interaction-service.service';
#Component({
selector: 'my-app',
templateUrl: 'app.component.html',
providers: [CourseService, InteractionService]
})
export class AppComponent implements OnInit {
searchStr: string;
constructor(private _courseService: CourseService, private _interactionService: InteractionService, private router: Router) {
}
ngOnInit() {
}
searchCourse(event) {
this._interactionService.sendString(event.target.value);
this.router.navigateByUrl('/');
}
}
course-listings.component.ts (I referred to this as results above)
// other imports
import {Subscription} from 'rxjs';
import {InteractionService} from '../interaction-service.service';
#Component({
selector: 'app-course-listings',
templateUrl: './course-listings.component.html',
providers: [CourseService],
})
export class CourseListingsComponent implements OnInit {
//some other properties defined
#Input() searchStr: string;
subscription: Subscription;
constructor(private _courseService: CourseService, private _interactionService: InteractionService) {
this.subscription = this._interactionService.searchStr$.subscribe(
courses => {
this.searchStr = courses;
// code for returning results here..
}
);
}
ngOnInit() {
}
}
Your right that you want to use a service. Services are singletons so setting in one component and getting from another will return the passed value.
To get a service to work you need to create the service then add it to your app module. Then in the constructor for your component you add it so the dependency injection can add it to the component for you. The constructor looks like this.
constructor( private router: Router){}
Each component should have a reference in its constructor and the service singleton is shared.
interaction-service.service.ts:
import { Injectable } from '#angular/core';
import { Subject } from 'rxjs/Subject';
#Injectable()
export class InteractionService {
sharedString = "";
}
app.component.ts:
import {InteractionService} from './interaction-service.service';
#Component({
selector: 'my-app',
templateUrl: 'app.component.html',
providers: [CourseService, InteractionService]
})
export class AppComponent implements OnInit {
constructor(private _courseService: CourseService, private _interactionService: InteractionService, private router: Router) {
}
ngOnInit() {
this.__interactionService.sharedString = "Some value";
}
searchCourse(event) {
this._interactionService.sendString(event.target.value);
this.router.navigateByUrl('/');
}
}
I'm going to leave the rest of the code out. The above example should be enough. Simply make the injected interaction service available and set and get the values at will. The service values will persist until there is a browser context change. Last thing I want to mention is when routing call the router like this
this.router.navigate(["url", someParam]);
this will preserve context and not cause a browser context switch when moving between components.
I have TypeScript code:
// app.js
import * as angular from 'angular';
import { Deamon } from 'Deamon';
angular.module('app')
.service('deamon', DeamonClass);
// Deamon.ts
export class DeamonClass {
$inject = [
'$vk'
];
constructor(private $vk: any) {} // <- $vk is my another service VkClass
}
How do I specify the type from $vk? If I point as the type name of the class,
constructor(private $vk: VkClass) {}
then nothing does not compile.
So I have my classes defined in angular factory functions:
export default function ($resource, $http:angular.IHttpService) {
return class Account{}
}
I also have a all.ts where my typings of definitelytyped are included. When I want to use Account in another class, I inject it with:
class AccountsController {
public static $inject = ['Account'];
constructor(public Account:Account){}
}
However, Account is unknown and even if I add the factory file to all.ts references, it does not find it.
How can I make Account known to typescript, ideally without defining the interface again (as it is already defined through the class, isn't it?).
I usually do it like this:
export function theService(...): theService {
return {
theServiceMethod1: function(id) {
}
}
export declare interface theService {
theServiceMethod1(id): void;
....
}
The same can be applied to a class as well. The class members are known, but the return type of the exported functions are not as far as I can tell.
I am creating an app with TypeScript and AngularJS 1, and I have run into a problem with creating a constant and passing the constant to the other class. I have the following constant in my app:
module app{
export class AUTH_EVENTS {
static get Default():any {
return {
LOGIN_SUCCESS: 'AUTH_EVENTS:LOGIN_SUCCESS',
LOGIN_FAILED: 'AUTH_EVENTS:LOGIN_FAILED',
LOGOUT_SUCCESS: 'AUTH_EVENTS:LOGOUT_SUCCESS',
LOGOUT_FAILED: 'AUTH_EVENTS:LOGOUT_FAILED',
SESSION_TIMEOUT: 'AUTH_EVENTS:SESSION_TIMEOUT',
NOT_AUTHORIZED: 'AUTH_EVENTS:NOT_AUTHORIZED'
};
}
}
var app = getModule();
app.constant("AUTH_EVENTS", AUTH_EVENTS.Default())
}
Which I try to access here:
module app{
class auth{
constructor(public $q: ng.IQService,
public $state:angular.ui.IState,
public AUTH_EVENTS: AUTH_EVENTS){
}
responseError(response:any) {
if (response.status === 401) {
console.log(this.AUTH_EVENTS.LOGIN_SUCCESS);
}
return this.$q.reject(response);
}
}
}
The issue that I have, is that in
console.log(this.AUTH_EVENTS.LOGIN_SUCCESS)
the LOGIN_SUCCESS is not defined.
Do you have any ideas why is this happening? Is there any issue with defining the constant, or is it the issue with the class auth. To be more specific, this is the error that I get when I compile TS into JS:
error TS2339: Property 'LOGIN_SUCCESS' does not exist on type 'AUTH_EVENTS'.
What about this definiton:
module app{
export class AUTH_EVENTS {
LOGIN_SUCCESS= 'AUTH_EVENTS:LOGIN_SUCCESS';
LOGIN_FAILED= 'AUTH_EVENTS:LOGIN_FAILED';
LOGOUT_SUCCESS= 'AUTH_EVENTS:LOGOUT_SUCCESS';
LOGOUT_FAILED= 'AUTH_EVENTS:LOGOUT_FAILED';
SESSION_TIMEOUT= 'AUTH_EVENTS:SESSION_TIMEOUT';
NOT_AUTHORIZED= 'AUTH_EVENTS:NOT_AUTHORIZED';
static Default() { return new AUTH_EVENTS(); }
}
var app = getModule();
app.constant("AUTH_EVENTS", AUTH_EVENTS.Default())
}
How to create marionete module using type script. I saw this how to write marionettejs module using typescript? but its not usefull for my case. I created module like
class TestModule extends Marionette.Module {
constructor(options) {
if (!options)
options = {};
var marionetteApp = new MarionetteApp();
marionetteApp.module("myModule", {
startWithParent: false
});
super("myModule", marionetteApp);
}
}
but its shows error
Unhandled exception at line 3561, column 5 in http://localhost/Scripts/backbone.marionette.js
0x800a138f - JavaScript runtime error: Unable to get property 'initialize' of undefined or null reference
What Im doing wrong. I am new to Marionette and typescript. What is the correct procedure to create marionette module using typescript
My application code is
class MarionetteApp extends Marionette.Application {
headerRegion: Marionette.Region;
leftRegion: Marionette.Region;
centerRegion: Marionette.Region;
constructor() {
super();
this.on("start", this.initializeAfter);
this.addRegions({ headerRegion:"#headerContainer",leftRegion:"#leftContainer",centerRegion:"#centerContainer"});
}
initializeAfter() {
//alert("started")
this.headerRegion.show(new HeaderView());
this.leftRegion.show(new leftView());
this.centerRegion.show(new CenterView());
var MyModule = new TestModule("Test");
//MyModule.start();
}
}
I fixed the issue using following code. Wrapped module inside a class. Its working as expected. Please correct me if I am wrong and anyone knows the correct procedure
class TestModule {
mod: any;
constructor() {
var marionetteApp = new MarionetteApp();
this.mod = marionetteApp.module("myModule", {
startWithParent: false,
initialize: function(){
console.log("initialized");
},
define: function () {
console.log("defined");
}
});
this.mod.on("start", this.onStart);
}
start() {
this.mod.start();
}
onStart() {
console.log("Module started")
}
}
initialization code
var MyModule = new TestModule();
MyModule.start();