当CMS显示index.html页面时,CMS会对其进行预解析,并在将页面发送到浏览器之前替换一些令牌(即[ModuleContext:ModuleId]).
这是我的index.html页面的示例(abreviated):
<!-- 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类声明之前使用declare来强制执行此操作,如下所示:
//Global Variable Declarations declare var $: any; declare var moduleId: any;
题:
什么是捕获这些“全局”变量的更好方法(如果存在),以便在可扩展的应用程序中使用.
编辑 – 更新到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(),在那里添加了提供者而不是在boostrap(…)中. Alsoprovide()`已被弃用并删除,以支持对象文字语法:
在共享库中定义
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,]); }) 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.