I've been working on this for a while now and can't seem to find an answer clear enough to understand. I have a TestComponent that grabs an array of TestModels from a server using TestService. When I grab these test models it is just a json file that the server is reading and sending back with the correct mime type. Once the test models are grabbed from the server, I put them in a simple select element drop down. When a test model is selected it display the selected test model in a nested component, TestDetailComponent.
That is all well and good and is working fine. I keep running into issues when I am pulling in the data from the server. Since JavaScript has no runtime checking we can't automatically cast the JSON from the server to a typescript class so I need to manually create a new instance of the TestModel with the retreived JSON.
Okay so here is the problem. I need to call new TestModel and give it its dependencies but it needs to be a new instance of TestModel. I want the TestModel to be able to save and update itself back to the server so it has a dependency on Http from @angular/core and it has a dependency on a config class I made that the angular injects with an opaqueToken, CONFIG.I can't figure out how to get new instances of TestModel. Here are the initial files
TestComponent:
import { Component, OnInit } from '@angular/core';
import { TestService } from './shared/test.service';
import { TestModel } from './shared/test.model';
import { TestDetailComponent } from './test-detail.component';
@Component({
selector: "test-component",
templateUrl: 'app/test/test.component.html',
styleUrls: [],
providers: [TestService],
directives: [TestDetailComponent]
})
export class TestComponent implements OnInit {
tests: TestModel[] = [];
selectedTest: TestModel;
constructor(private testService: TestService) {};
ngOnInit() {
this.testService.getTestsModels().subscribe( (tests) => {
console.log(tests);
this.tests = tests
});
}
}
TestComponent template:
<select [(ngModel)]="selectedTest">
<option *ngFor="let test of tests" [ngValue]="test">{{test.testing}}</option>
</select>
<test-detail *ngIf="selectedTest" [test]="selectedTest"></test-detail>
TestDetailComponent:
import { Component, Input } from '@angular/core';
import { JsonPipe } from '@angular/common';
import { TestModel } from './shared/test.model';
@Component({
selector: 'test-detail',
templateUrl: 'app/test/test-detail.component.html',
pipes: [JsonPipe]
})
export class TestDetailComponent {
@Input() test;
}
TestDetailComponent template
<p style="font-size: 3em;">{{test | json}}</p>
TestModel
import { Injectable, Inject } from '@angular/core';
import { Http, Response, Headers, RequestOptions } from '@angular/http';
import { Observable } from 'rxjs/Rx';
import { CONFIG } from './../../config/constants';
@Injectable()
export class TestModel {
"testing": number;
"that": string;
"a": string;
constructor(private http: Http, @Inject(CONFIG) private config) {}
save(): Observable<TestModel[]> {
let url = this.config.apiUrl + "test";
let body = JSON.stringify({
testing: this.testing,
this: this.that,
a: this.a
});
let headers = new Headers({'Content-Type': 'application/json'});
let options = new RequestOptions({headers: headers});
return this.http.post(url, body, options)
.map( (response) => response.json() )
.map( (results) => {
results.map( (aggregate, current) => {
aggregate.push(<TestModel>current);
return aggregate;
}, new Array<TestModel>())
}).catch(this.handleError);
}
update() {
let url = this.config.apiUrl + "test";
let body = JSON.stringify({
testing: this.testing,
this: this.that,
a: this.a
});
let headers = new Headers({'Content-Type': 'application/json'});
let options = new RequestOptions({headers: headers});
return this.http.put(url, body, options)
.map( (response) => response.json() )
.map( (results) => {
results.map( (aggregate, current) => {
aggregate.push(<TestModel>current);
return aggregate;
}, new Array<TestModel>())
}).catch(this.handleError);
}
private handleError(err): Observable<any> {
let errMessage = err.message ? err.message : err.status ? `${err.status} - ${err.statusText}` : 'Server Error';
return Observable.throw(new Error(errMessage));
}
}
Test Service
import { Injectable, Inject } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Rx';
import { CONFIG } from './../../config/constants';
import { TestModel } from './test.model';
@Injectable()
export class TestService {
constructor(private http: Http, @Inject(CONFIG) private config) {}
getTestsModels(): Observable<TestModel[]> {
let url = this.config.apiUrl + "test";
return this.http.get(url)
.map( (response) => response.json() )
.map( (results) => {
return results.map( (current) => {
return <TestModel>current; // <<<--- here is the error
})
})
.catch(this.handleError);
}
private handleError(err): Observable<any> {
let errMessage = err.message ? err.message : err.status ? `${err.status} - ${err.statusText}` : 'Server Error';
return Observable.throw(new Error(errMessage));
}
}
I have tried using the ReflectiveInjector so TestService becomes this:
import { Injectable, Inject, ReflectiveInjector } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Rx';
import { CONFIG } from './../../config/constants';
import { TestModel } from './test.model';
@Injectable()
export class TestService {
constructor(private http: Http, @Inject(CONFIG) private config) {}
getTestsModels(): Observable<TestModel[]> {
let url = this.config.apiUrl + "test";
return this.http.get(url)
.map( (response) => response.json() )
.map( (results) => {
return results.map( (current) => {
return ReflectiveInjector.resolveAndCreate([TestModel]).get(TestModel);
})
})
.catch(this.handleError);
}
private handleError(err): Observable<any> {
let errMessage = err.message ? err.message : err.status ? `${err.status} - ${err.statusText}` : 'Server Error';
return Observable.throw(new Error(errMessage));
}
}
But then I just get the error:
Then if I add Http to the ReflectiveInjector I just get another connection backend error and I am assuming that would keep going to the dependency chain till we found the bottom.
Sorry for the long post, any help would be appreciated!
See Question&Answers more detail:
os