2016-11-22 42 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" 
     } 
    } 
} 

当服务器应用程序构建时,编译器将导入服务器模块而不是浏览器模块。