Bea*_*180 2 dependency-injection typescript angular
我已经在这方面工作了一段时间,似乎无法找到足够明白的答案.我有一个TestComponent,它使用TestService从服务器获取一组TestModel.当我抓住这些测试模型时,它只是一个json文件,服务器正在读取并使用正确的mime类型发回.从服务器获取测试模型后,我将它们放在一个简单的select元素下拉列表中.选择测试模型后,它会在嵌套组件TestDetailComponent中显示所选的测试模型.
这一切都很好,并且工作正常.当我从服务器提取数据时,我一直遇到问题.由于JavaScript没有运行时检查,我们无法自动将JSON从服务器转换为typescript类,因此我需要使用已检索的JSON手动创建TestModel的新实例.
好的,这就是问题所在.我需要调用新的TestModel并为其提供依赖项,但它需要是TestModel的新实例.我希望TestModel能够将自身保存并更新回服务器,因此它依赖于来自@ angular/core的Http,并且它依赖于我使用opaqueToken,CONFIG.I进行角度注入的配置类.无法弄清楚如何获得TestModel的新实例.这是初始文件
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
});
}
}
Run Code Online (Sandbox Code Playgroud)
TestComponent模板:
<select [(ngModel)]="selectedTest">
<option *ngFor="let test of tests" [ngValue]="test">{{test.testing}}</option>
</select>
<test-detail *ngIf="selectedTest" [test]="selectedTest"></test-detail>
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
TestDetailComponent模板
<p style="font-size: 3em;">{{test | json}}</p>
Run Code Online (Sandbox Code Playgroud)
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));
}
}
Run Code Online (Sandbox Code Playgroud)
测试服务
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));
}
}
Run Code Online (Sandbox Code Playgroud)
我尝试过使用ReflectiveInjector,因此TestService成为:
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));
}
}
Run Code Online (Sandbox Code Playgroud)
但后来我得到了错误:
然后,如果我将Http添加到ReflectiveInjector我只是得到另一个连接后端错误,我假设将继续到依赖链,直到我们找到底部.
对不起,很长的帖子,任何帮助将不胜感激!
Gün*_*uer 10
您可以提供工厂功能.这与简单的useFactory: ...提供商不同
{
provide: 'TestModelFactory',
useFactory: () => {
return (http, config) => {
return new TestModel(http, config);
};
},
deps: [Http, CONFIG];
}
Run Code Online (Sandbox Code Playgroud)
然后像使用它一样
@Injectable()
export class TestService {
constructor(@Inject('TestModelFactory' testModelFactory) {}
getTestsModels(): Observable<TestModel[]> {
let url = this.config.apiUrl + "test";
return this.http.get(url)
.map( (response) => response.json() )
.map( (results) => {
return results.map( (current) => {
let tm = testModelFactory();
tm.xxx // assign data
})
})
.catch(this.handleError);
}
}
Run Code Online (Sandbox Code Playgroud)
您还可以支持每个实例参数
{
provide: 'TestModelFactory',
useFactory: (json) => {
return (http, config) => {
return new TestModel(http, config, json);
};
},
deps: [Http, CONFIG];
}
Run Code Online (Sandbox Code Playgroud)
然后像使用它一样
@Injectable()
export class TestService {
constructor(@Inject('TestModelFactory' testModelFactory) {}
getTestsModels(): Observable<TestModel[]> {
let url = this.config.apiUrl + "test";
return this.http.get(url)
.map( (response) => response.json() )
.map( (results) => {
return results.map( (current) => {
let tm = testModelFactory(result);
})
})
.catch(this.handleError);
}
}
Run Code Online (Sandbox Code Playgroud)
但是你不需要使用DI.你已经注入Http并CONFIG进入你的TestService.你可以
@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 new TestModel(http, config);
})
})
.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));
}
}
Run Code Online (Sandbox Code Playgroud)
在任何情况下,你需要提供一些方法来初始化TestModel从result通过传递JSON的构造函数,例如和初始化的成员TestModel从通过JSON.
| 归档时间: |
|
| 查看次数: |
14928 次 |
| 最近记录: |