2016-11-22 26 views
2

是否可以根據條件導入模塊?只有在角色2通用應用程序在瀏覽器中呈現但不在服務器中時,纔會導入外部模塊。角度通用:僅針對瀏覽器的動態導入

此問題與某些依賴瀏覽器功能且只能在瀏覽器中呈現的PrimeNG模塊相關。在服務器渲染中忽略它們會很好,因爲日曆和其他組件對於搜索引擎優化並不重要。

目前我可以渲染日曆組件,如果關閉服務器渲染。但是,當我將下面的代碼包含在我的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

你知道如何用isPlatformBrowser而不是isBrowser做到這一點嗎? –

+0

@RaymondtheDeveloper我認爲isPlatformBrowser應該在Universal的「Gotchas」部分中描述[這裏](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" 
     } 
    } 
} 

當服務器應用程序構建時,編譯器將導入服務器模塊而不是瀏覽器模塊。