2016-11-22 3 views
2

条件に基づいてモジュールをインポートすることはできますか?角度2のユニバーサルアプリケーションがブラウザではレンダリングされているが、サーバではレンダリングされていない場合にのみ、特に外部モジュールをインポートする。angular universal:ブラウザ専用の動的インポート

この質問は、ブラウザの機能に依存するいくつかのPrimeNGモジュールに関連し、ブラウザでしか表示できません。サーバーレンダリングのカレンダーやその他のコンポーネントがSEOにとって本当に重要ではないという理由で、それらを省略するとよいでしょう。

現在、サーバーレンダリングをオフにすると、カレンダーコンポーネントをレンダリングできます。しかし、以下のコードを私のapp.module.tsに組み込み、サーバーレンダリングをオンにすると、サーバーはbutton.jsで 'ReferenceError:Event is not defined'というエラーを生成します。

import { CalendarModule } from 'primeng/components/calendar/calendar'; 
 
@NgModule({ 
 
    ... 
 
    imports: [ 
 
     ..., 
 
     CalendarModule 
 
    ] 
 
})

角度によって提供さisBrowser条件があります。

import { isBrowser } from 'angular2-universal';

しかし、私は条件付き輸入のためにそれを使用する方法がわかりません。モジュールのために実際に行う方法はありますか?

答えて

4

したがって、PrimeNGコンポーネントをブラウザでレンダリングし、サーバレンダリング時にそれらのコンポーネントを省略する方法があります。これらの質問は私が正しい方向を掘り始める助け:

angular-cli: Conditional Imports using an environment variable

How can I conditionally import an ES6 module?

サーバーは、私は、単純な入力フィールドをレンダリングし、同じセレクタ「P-カレンダー」を使用していますモックコンポーネントを使用しレンダリングしながら。最後のコードは私のapp.moduleで終わりました。

...//other imports 
 
import { isBrowser } from 'angular2-universal'; 
 

 
let imports = [ 
 
    ... //your modules here 
 
]; 
 
let declarations = [ 
 
    ... //your declarations here 
 
]; 
 

 
if (isBrowser) { 
 
    let CalendarModule = require('primeng/components/calendar/calendar').CalendarModule; 
 
    imports.push(CalendarModule); 
 
} 
 
else { 
 
    let CalendarMockComponent = require('./components/primeng/calendarmock.component').CalendarMockComponent; 
 
    declarations.push(CalendarMockComponent); 
 
} 
 

 
@NgModule({ 
 
    bootstrap: [AppComponent], 
 
    declarations: declarations, 
 
    providers: [ 
 
     ... //your providers here 
 
    ], 
 
    imports: imports 
 
})

このチュートリアルあなたのモックコンポーネントのサポート[(ngModel)]結合に活用します。 http://almerosteyn.com/2016/04/linkup-custom-control-to-ngcontrol-ngmodel

import { Component, forwardRef } from '@angular/core'; 
 
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms'; 
 

 
export const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = { 
 
    provide: NG_VALUE_ACCESSOR, 
 
    useExisting: forwardRef(() => CalendarMockComponent), 
 
    multi: true 
 
}; 
 

 
@Component({ 
 
    selector: 'p-calendar', 
 
    template: '<input type="text" class="form-control"/>', 
 
    providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR] 
 
}) 
 
export class CalendarMockComponent implements ControlValueAccessor { 
 

 
    private innerValue: any = ''; 
 

 
    private onTouchedCallback:() => void =() => {}; 
 
    private onChangeCallback: (_: any) => void =() => {}; 
 

 
    //From ControlValueAccessor interface 
 
    writeValue(value: any) { 
 
     if (value !== this.innerValue) { 
 
      this.innerValue = value; 
 
     } 
 
    } 
 

 
    registerOnChange(fn: any) { 
 
     this.onChangeCallback = fn; 
 
    } 
 

 
    registerOnTouched(fn: any) { 
 
     this.onTouchedCallback = fn; 
 
    } 
 
}

+0

isBlasterではなくisPlatformBrowserでこれを行う方法を知っていますか? –

+0

@RaymondtheDeveloper私はisPlatformBrowserがUniversal "Gotchas"セクションで[here](https://www.npmjs.com/package/angular4-aspnetcore-universal)に記載されているように動作すると思います。それ以外はisBrowserと同じでなければなりません。試してみる。 – Rodion

+0

問題はapp.module.ts内で使用したいということです。そこにPLATFORM_IDを注入する方法がわかりません。また、isPlatformBrowserはPLATFORM_IDが必要です。 –

0

動的なスクリプトのロードを必要としないモジュールの輸入のための代替ソリューション:あなたはサーバ - にインポートモジュールをリダイレクトするために、サーバーアプリケーションのtsconfig.jsonファイルにcompilerOptions.pathsオプションを使用することができます唯一のバージョン:

{ 
    ... 
    "compilerOptions": { 
     ... 
     "paths": { 
      "path/to/browser/module": "path/to/server/module" 
     } 
    } 
} 

サーバーアプリケーションがビルドされると、コンパイラはブラウザモジュールの代わりにサーバーモジュールをインポートします。

関連する問題