如何将后端渲染的参数传递给angular2 bootstrap方法 [英] How to pass parameters rendered from backend to angular2 bootstrap method
问题描述
有没有办法将后端呈现的参数传递给 angular2 bootstrap 方法?我想使用 BaseRequestOptions 与后端提供的值.我的 main.ts
文件如下所示:
Is there a way to pass arguments rendered on the backend to angular2 bootstrap method? I want to set http header for all requests using BaseRequestOptions with value provided from the backend. My main.ts
file looks like this:
import { bootstrap } from '@angular/platform-browser-dynamic';
import { AppComponent } from "./app.component.ts";
bootstrap(AppComponent);
我找到了如何将此参数传递给根组件 (https://stackoverflow.com/a/35553650/3455681),但是当我触发 bootstrap
方法时我需要它......有什么想法吗?
I found how to pass this arguments to root component (https://stackoverflow.com/a/35553650/3455681), but i need it when I'm fireing bootstrap
method... Any ideas?
webpack.config.js 内容:
webpack.config.js content:
module.exports = {
entry: {
app: "./Scripts/app/main.ts"
},
output: {
filename: "./Scripts/build/[name].js"
},
resolve: {
extensions: ["", ".ts", ".js"]
},
module: {
loaders: [
{
test: /.ts$/,
loader: 'ts-loader'
}
]
}
};
推荐答案
update2
更新 AoT
为了与 AoT 合作,需要搬出工厂关闭
To work with AoT the factory closure needs to be moved out
function loadContext(context: ContextService) {
return () => context.load();
}
@NgModule({
...
providers: [ ..., ContextService, { provide: APP_INITIALIZER, useFactory: loadContext, deps: [ContextService], multi: true } ],
另见https://github.com/angular/angular/issues/11262
更新一个 RC.6 和 2.0.0 最终示例
update an RC.6 and 2.0.0 final example
function configServiceFactory (config: ConfigService) {
return () => config.load();
}
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule,
routes,
FormsModule,
HttpModule],
providers: [AuthService,
Title,
appRoutingProviders,
ConfigService,
{ provide: APP_INITIALIZER,
useFactory: configServiceFactory
deps: [ConfigService],
multi: true }
],
bootstrap: [AppComponent]
})
export class AppModule { }
如果不需要等待初始化完成,也可以使用`class AppModule {}的构造函数:
If there is no need to wait for the initialization to complete, the constructor of `class AppModule {} can also be used:
class AppModule {
constructor(/*inject required dependencies */) {...}
}
提示(循环依赖)
例如注入路由器会导致循环依赖.要解决此问题,请注入 Injector
并通过
For example injecting the router can cause cyclic dependencies.
To work around, inject the Injector
and get the dependency by
this.myDep = injector.get(MyDependency);
而不是像这样直接注入 MyDependency
:
instead of injecting MyDependency
directly like:
@Injectable()
export class ConfigService {
private router:Router;
constructor(/*private router:Router*/ injector:Injector) {
setTimeout(() => this.router = injector.get(Router));
}
}
更新
这应该在 RC.5 中工作相同,但将提供程序添加到根模块的 providers: [...]
而不是 bootstrap(...)
This should work the same in RC.5 but instead add the provider to providers: [...]
of the root module instead of bootstrap(...)
(我还没有测试过).
更新
这里解释了一种完全在 Angular 内部完成的有趣方法https://github.com/angular/angular/issues/9047#issuecomment-224075188
An interesting approach to do it entirely inside Angular is explained here https://github.com/angular/angular/issues/9047#issuecomment-224075188
您可以使用 APP_INITIALIZER
来执行一个函数应用程序被初始化并在函数返回时延迟它提供的内容一个承诺.这意味着应用程序可以在没有完全初始化的情况下进行初始化很多延迟,你也可以使用现有的服务和框架功能.
You can use
APP_INITIALIZER
which will execute a function when the app is initialized and delay what it provides if the function returns a promise. This means the app can be initializing without quite so much latency and you can also use the existing services and framework features.
例如,假设您有一个多租户解决方案,其中站点信息依赖于提供服务的域名.这个可以是 [name].letterpress.com 或匹配的自定义域完整的主机名.我们可以隐藏一个事实,即这是在承诺背后使用 APP_INITIALIZER
.
As an example, suppose you have a multi-tenanted solution where the
site info relies on the domain name it's being served from. This can
be [name].letterpress.com or a custom domain which is matched on the
full hostname. We can hide the fact that this is behind a promise by
using APP_INITIALIZER
.
在引导程序中:
{provide: APP_INITIALIZER, useFactory: (sites:SitesService) => () => sites.load(), deps:[SitesService, HTTP_PROVIDERS], multi: true}),
sites.service.ts:
sites.service.ts:
@Injectable()
export class SitesService {
public current:Site;
constructor(private http:Http, private config:Config) { }
load():Promise<Site> {
var url:string;
var pos = location.hostname.lastIndexOf(this.config.rootDomain);
var url = (pos === -1)
? this.config.apiEndpoint + '/sites?host=' + location.hostname
: this.config.apiEndpoint + '/sites/' + location.hostname.substr(0, pos);
var promise = this.http.get(url).map(res => res.json()).toPromise();
promise.then(site => this.current = site);
return promise;
}
注意:config
只是一个自定义配置类.rootDomain
将是'.letterpress.com'
对于此示例,并允许诸如aptaincodeman.letterpress.com
.
NOTE: config
is just a custom config class. rootDomain
would be
'.letterpress.com'
for this example and would allow things like
aptaincodeman.letterpress.com
.
任何组件和其他服务现在都可以将 Site
注入到它们并使用 .current
属性,这将是一个具体的填充对象,无需等待应用内的任何承诺.
Any components and other services can now have Site
injected into
them and use the .current
property which will be a concrete
populated object with no need to wait on any promise within the app.
这种方法似乎减少了启动延迟,否则如果您正在等待大型 Angular 包在引导程序开始之前加载然后另一个 http 请求.
This approach seemed to cut the startup latency which was otherwise quite noticeable if you were waiting for the large Angular bundle to load and then another http request before the bootstrap even began.
原创
您可以使用 Angulars 依赖注入来传递它:
You can pass it using Angulars dependency injection:
var headers = ... // get the headers from the server
bootstrap(AppComponent, [{provide: 'headers', useValue: headers})]);
class SomeComponentOrService {
constructor(@Inject('headers') private headers) {}
}
或者直接像
class MyRequestOptions extends BaseRequestOptions {
constructor (private headers) {
super();
}
}
var values = ... // get the headers from the server
var headers = new MyRequestOptions(values);
bootstrap(AppComponent, [{provide: BaseRequestOptions, useValue: headers})]);
这篇关于如何将后端渲染的参数传递给angular2 bootstrap方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!