将 Page/Global 变量传递给 Angular2 应用程序以用于服务
Pass Page/Global Variables into Angular2 app for use with services
我正在寻找一些最佳实践。我的 angular2 应用程序将存在于现有的内容管理系统中。因此,我需要捕获此 CMS 生成的一些 "variables"(如身份验证令牌等),并将它们与我的 angular2 应用程序中的 http 请求一起使用。
当 CMS 显示 index.html 页面时,CMS 会对其进行预解析,并在将页面发送到浏览器之前替换一些标记(即 [ModuleContext:ModuleId])。
这是我的 index.html 页面的示例(缩写):
<!-- 2. Capture CMS values to pass to app -->
<script type="text/javascript">
var moduleId = parseInt("[ModuleContext:ModuleId]");
var portalId = parseInt("[ModuleContext:PortalId]");
var sf = $.ServicesFramework(moduleId);
</script>
<!-- 3. Configure SystemJS and Bootstrap App-->
<script type="text/javascript">
System.config({
packages: {
//sets the root path of the Angular2 App
'DesktopModules/KrisisShifts/app': {
format: 'register',
defaultExtension: 'js'
}
},
map: { 'app': './app' }
});
System.import('app/boot')
.then(null, console.error.bind(console));
</script>
<shift-app>Loading...</shift-app>
特别是 $.ServicesFramework 用于生成有效的 http web.api 请求。我想在可以注入到使用它的每个组件中的服务中捕获它。
例如(我使用的是打字稿):
import {Injectable} from 'angular2/core';
import {OnInit} from 'angular2/core';
@Injectable()
export class dnnService implements OnInit{
sf: any;
constructor() {}
ngOnInit() {
if ($.ServicesFramework) {
this.sf = $.ServicesFramework(moduleId);
};
}
}
一个问题是 typescript 编译器抛出找不到“$”等错误。我可以通过在 typescript class 声明之前使用 declare 来强制它工作,如下所示:
//Global Variable Declarations
declare var $: any;
declare var moduleId: any;
问题:
什么是捕获这些 "global" 变量的更好方法(如果存在),以便在可以很好扩展的应用中使用。
编辑 - 更新到 RC6
我使用以下工具在 RC6 中工作:
@NgModule({
declarations: [
AppComponent,
FormatDatePipe,
ShiftPartialPipe
],
imports: [
BrowserModule,
RouterModule.forRoot(AppRoutes),
FormsModule,
ReactiveFormsModule,
HttpModule
],
bootstrap: [AppComponent],
providers: [
{ provide: LocationStrategy, useClass: HashLocationStrategy },
{ provide: dnnModId, useValue: moduleId },
{ provide: dnnPortalId, useValue: portalId },
{ provide: dnnEditMode, useValue: editMode },
{ provide: dnnSF, useValue: $.ServicesFramework(moduleId) }
]
})
更新>=RC.6
在引入 @NgModule()
的 RC.6 中,提供程序被添加到那里而不是在 boostrap(...). Also
provide()` 中被弃用和删除以支持对象文字语法:
在共享库中定义
import {OpaqueToken} from '@angular/core';
export let SF = new OpaqueToken('sf');
@NgModule({
providers: [{provide: SF, useValue: $.ServicesFramework(moduleId)},
directives: [...]
...
})
class SomeModule {}
提供者也可以添加到组件和指令中
@Component({
providers: [
{provide: SF, useValue: $.ServicesFramework(moduleId)},
]);
})
class SomeComponent {}
将其注入组件、指令、管道或类似服务
constructor(@Inject(SF) private sf:string) {}
原创
在共享库中定义
import {OpaqueToken} from '@angular/core';
export let SF = new OpaqueToken('sf');
在bootstrap()
中添加
// import SF from shared library
bootstrap(AppComponent, [
// other providers
provide(SF, {useValue: $.ServicesFramework(moduleId)}),
]);
你想在哪里使用它
// import SF from shared library
constructor(@Inject(SF) private _sf: string){ }
这利用了 Angulars DI 并避免了使代码难以测试的硬编码依赖项。
另见
- https://angular.io/docs/ts/latest/guide/dependency-injection.html
- http://blog.thoughtram.io/angular2/2015/11/23/multi-providers-in-angular-2.html
提示:
也可以使用普通字符串代替 OpaqueToken
。使用 OpaqueToken
可以防止名称冲突,例如,如果它用于许多用户使用的开源包中。如果您控制了整个环境,那么您可以确保自己不会发生碰撞,并且应该安全地使用字符串而不是 OpaqueToken
.
更新
引入了具有泛型支持的 InjectionToken
以取代现已弃用的 OpaqueToken
。
为了稍微扩展 Gunther 的答案,我也在 RC5 中完成了此操作,只是没有将其添加到 bootstrap() 中的提供者(从以前的版本开始),而是将令牌作为提供者放置在正在执行 bootstrapping 的新 @ngModule 装饰器。例如:
@NgModule({
bootstrap: [MyComponent],
declarations: [MyComponent],
imports: [BrowserModule],
providers: [
{ provide: OpaqueToken, useValue: someObject }
]
})
export class AppModule { }
browserDynamicPlatform().bootstrapModule(AppModule);
不确定这是否是最佳做法,但我遇到了同样的问题,我正在使用的解决方案(RC5 就绪)如下:
步骤 1) 创建您的设置 class 作为 @Injectable:
import { Injectable } from '@angular/core';
@Injectable()
export class MyAppSharedSettings {
appName: string = "My Application Name";
appTitle: string = "My Application Title";
appVersion: string = "1.0.0.0 beta";
welcomeMessage: string = "Welcome";
userName: string = "";
}
步骤 2) 在您的主模块上,导入以下内容(如果您尚未这样做):
//Imports required for NgModule directive
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpModule } from '@angular/http';
//Imports required for your code to run
import { MyAppMainComponent } from './myapp.component';
import { MyAppSharedSettings } from './myapp.shared-settings';
第 3 步)因此,您已将 class 标记为可注入(第一步),并且还使其可用于(提供者)任何想要使用它的组件(第 2 步)。现在,下一步就是将它放入组件的构造函数中。
//Imports: Angular & Packages Related
import { Component, Inject } from '@angular/core';
//You must import your injectable class in every component you plan to use it
import { MyAppSharedSettings } from '../../myapp.shared-settings';
//defining how our component will be presented/used
@Component({
selector: 'my-content',
templateUrl: './app/components/content/content.component.html',
styleUrls: ['./app/components/content/content.component.css']
})
//here you name your variable as you please
export class MyContent {
yourVariableName: MyAppSharedSettings;
constructor(private eafSettings: MyAppSharedSettings) {
this.yourVariableName = eafSettings;
}
}
最后一步)这里是我们如何在 HTML:
中使用它
<h3 class="page-title">
{{ yourVariableName.welcomeMessage }}<small> {{ yourVariableName.userName}}</small>
</h3>
<div class="row about-header">
<div class="col-md-12">
<h1>{{ yourVariableName.appName}}</h1>
<h2>{{ yourVariableName.appTitle }}</h2>
<a href="#platform"><button type="button" class="btn btn-danger uppercase">Start</button></a>
</div>
</div>
</div>
希望对您有所帮助。
我正在寻找一些最佳实践。我的 angular2 应用程序将存在于现有的内容管理系统中。因此,我需要捕获此 CMS 生成的一些 "variables"(如身份验证令牌等),并将它们与我的 angular2 应用程序中的 http 请求一起使用。
当 CMS 显示 index.html 页面时,CMS 会对其进行预解析,并在将页面发送到浏览器之前替换一些标记(即 [ModuleContext:ModuleId])。
这是我的 index.html 页面的示例(缩写):
<!-- 2. Capture CMS values to pass to app -->
<script type="text/javascript">
var moduleId = parseInt("[ModuleContext:ModuleId]");
var portalId = parseInt("[ModuleContext:PortalId]");
var sf = $.ServicesFramework(moduleId);
</script>
<!-- 3. Configure SystemJS and Bootstrap App-->
<script type="text/javascript">
System.config({
packages: {
//sets the root path of the Angular2 App
'DesktopModules/KrisisShifts/app': {
format: 'register',
defaultExtension: 'js'
}
},
map: { 'app': './app' }
});
System.import('app/boot')
.then(null, console.error.bind(console));
</script>
<shift-app>Loading...</shift-app>
特别是 $.ServicesFramework 用于生成有效的 http web.api 请求。我想在可以注入到使用它的每个组件中的服务中捕获它。
例如(我使用的是打字稿):
import {Injectable} from 'angular2/core';
import {OnInit} from 'angular2/core';
@Injectable()
export class dnnService implements OnInit{
sf: any;
constructor() {}
ngOnInit() {
if ($.ServicesFramework) {
this.sf = $.ServicesFramework(moduleId);
};
}
}
一个问题是 typescript 编译器抛出找不到“$”等错误。我可以通过在 typescript class 声明之前使用 declare 来强制它工作,如下所示:
//Global Variable Declarations
declare var $: any;
declare var moduleId: any;
问题:
什么是捕获这些 "global" 变量的更好方法(如果存在),以便在可以很好扩展的应用中使用。
编辑 - 更新到 RC6
我使用以下工具在 RC6 中工作:
@NgModule({
declarations: [
AppComponent,
FormatDatePipe,
ShiftPartialPipe
],
imports: [
BrowserModule,
RouterModule.forRoot(AppRoutes),
FormsModule,
ReactiveFormsModule,
HttpModule
],
bootstrap: [AppComponent],
providers: [
{ provide: LocationStrategy, useClass: HashLocationStrategy },
{ provide: dnnModId, useValue: moduleId },
{ provide: dnnPortalId, useValue: portalId },
{ provide: dnnEditMode, useValue: editMode },
{ provide: dnnSF, useValue: $.ServicesFramework(moduleId) }
]
})
更新>=RC.6
在引入 @NgModule()
的 RC.6 中,提供程序被添加到那里而不是在 boostrap(...). Also
provide()` 中被弃用和删除以支持对象文字语法:
在共享库中定义
import {OpaqueToken} from '@angular/core';
export let SF = new OpaqueToken('sf');
@NgModule({
providers: [{provide: SF, useValue: $.ServicesFramework(moduleId)},
directives: [...]
...
})
class SomeModule {}
提供者也可以添加到组件和指令中
@Component({
providers: [
{provide: SF, useValue: $.ServicesFramework(moduleId)},
]);
})
class SomeComponent {}
将其注入组件、指令、管道或类似服务
constructor(@Inject(SF) private sf:string) {}
原创
在共享库中定义
import {OpaqueToken} from '@angular/core';
export let SF = new OpaqueToken('sf');
在bootstrap()
中添加
// import SF from shared library
bootstrap(AppComponent, [
// other providers
provide(SF, {useValue: $.ServicesFramework(moduleId)}),
]);
你想在哪里使用它
// import SF from shared library
constructor(@Inject(SF) private _sf: string){ }
这利用了 Angulars DI 并避免了使代码难以测试的硬编码依赖项。
另见
- https://angular.io/docs/ts/latest/guide/dependency-injection.html
- http://blog.thoughtram.io/angular2/2015/11/23/multi-providers-in-angular-2.html
提示:
也可以使用普通字符串代替 OpaqueToken
。使用 OpaqueToken
可以防止名称冲突,例如,如果它用于许多用户使用的开源包中。如果您控制了整个环境,那么您可以确保自己不会发生碰撞,并且应该安全地使用字符串而不是 OpaqueToken
.
更新
引入了具有泛型支持的InjectionToken
以取代现已弃用的 OpaqueToken
。
为了稍微扩展 Gunther 的答案,我也在 RC5 中完成了此操作,只是没有将其添加到 bootstrap() 中的提供者(从以前的版本开始),而是将令牌作为提供者放置在正在执行 bootstrapping 的新 @ngModule 装饰器。例如:
@NgModule({
bootstrap: [MyComponent],
declarations: [MyComponent],
imports: [BrowserModule],
providers: [
{ provide: OpaqueToken, useValue: someObject }
]
})
export class AppModule { }
browserDynamicPlatform().bootstrapModule(AppModule);
不确定这是否是最佳做法,但我遇到了同样的问题,我正在使用的解决方案(RC5 就绪)如下:
步骤 1) 创建您的设置 class 作为 @Injectable:
import { Injectable } from '@angular/core';
@Injectable()
export class MyAppSharedSettings {
appName: string = "My Application Name";
appTitle: string = "My Application Title";
appVersion: string = "1.0.0.0 beta";
welcomeMessage: string = "Welcome";
userName: string = "";
}
步骤 2) 在您的主模块上,导入以下内容(如果您尚未这样做):
//Imports required for NgModule directive
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpModule } from '@angular/http';
//Imports required for your code to run
import { MyAppMainComponent } from './myapp.component';
import { MyAppSharedSettings } from './myapp.shared-settings';
第 3 步)因此,您已将 class 标记为可注入(第一步),并且还使其可用于(提供者)任何想要使用它的组件(第 2 步)。现在,下一步就是将它放入组件的构造函数中。
//Imports: Angular & Packages Related
import { Component, Inject } from '@angular/core';
//You must import your injectable class in every component you plan to use it
import { MyAppSharedSettings } from '../../myapp.shared-settings';
//defining how our component will be presented/used
@Component({
selector: 'my-content',
templateUrl: './app/components/content/content.component.html',
styleUrls: ['./app/components/content/content.component.css']
})
//here you name your variable as you please
export class MyContent {
yourVariableName: MyAppSharedSettings;
constructor(private eafSettings: MyAppSharedSettings) {
this.yourVariableName = eafSettings;
}
}
最后一步)这里是我们如何在 HTML:
中使用它 <h3 class="page-title">
{{ yourVariableName.welcomeMessage }}<small> {{ yourVariableName.userName}}</small>
</h3>
<div class="row about-header">
<div class="col-md-12">
<h1>{{ yourVariableName.appName}}</h1>
<h2>{{ yourVariableName.appTitle }}</h2>
<a href="#platform"><button type="button" class="btn btn-danger uppercase">Start</button></a>
</div>
</div>
</div>
希望对您有所帮助。