5

ここでいくつかのベストプラクティスを探しています。私の angular2 アプリは、既存のコンテンツ管理システム内に存在します。その結果、この CMS によって生成されたいくつかの「変数」(認証トークンなど) を取得し、それらを angular2 アプリ内の http 要求で使用する必要があります。

index.html ページが CMS によって表示されると、ページがブラウザーに送信される前に、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>

具体的には、有効な http web.api リクエストを生成するために $.ServicesFramework が使用されます。これを、それを使用する各コンポーネントに注入できるサービスに取り込みたいと考えています。

たとえば(私はタイプスクリプトを使用しています):

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);
        };
    }

}

1 つの問題は、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) }
]
})
4

3 に答える 3

8

更新 >= RC.6

RC.6 では、 provider()@NgModule()の代わりにプロバイダーが追加さboostrap(...). Alsoれ、オブジェクト リテラル構文が優先されて削除されました。

共有ライブラリで定義

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 を利用し、コードのテストを困難にするハードコーディングされた依存関係を回避します。

こちらもご覧ください

ヒントOpaqueToken:単純な文字列の代わりに使用することもできます。を使用OpaqueTokenすると、たとえば、多くのユーザーが使用するオープン ソース パッケージでこれを使用する場合に、名前の衝突を防ぐことができます。完全な環境を制御する場合、衝突が発生しないことを確認でき、 の代わりに文字列を安全に使用できますOpaqueToken

アップデート

InjectionTokenジェネリックスのサポートが導入され、OpaqueToken現在は廃止されています。

于 2016-02-05T06:35:32.220 に答える
2

Gunther の回答を少し拡張するために、RC5 でもこれを行いましたが、bootstrap() (以前のバージョンから) でプロバイダーに追加する代わりに、トークンを新しい @ngModule デコレーターにプロバイダーとして配置します。ブートストラップ。例えば:

@NgModule({
    bootstrap: [MyComponent],
    declarations: [MyComponent],
    imports: [BrowserModule],
    providers: [
        { provide: OpaqueToken, useValue: someObject }
    ]
})
export class AppModule { }

browserDynamicPlatform().bootstrapModule(AppModule);
于 2016-08-18T04:07:33.773 に答える
0

それがベストプラクティスかどうかはわかりませんが、私は同じ問題に直面しており、私が使用している解決策 (RC5 対応) は次のとおりです。

ステップ 1) 設定クラスを @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) これで、クラスを注入可能としてマークし (ステップ 1)、それを使用したい任意のコンポーネントで使用できるように (プロバイダー) しました (ステップ 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>

それが役に立てば幸い。

于 2016-08-31T15:00:28.147 に答える