通用角度:仅用于浏览器的动态导入

Rod*_*ion 3 primeng angular-universal angular

是否可以根据条件导入模块?具体来说,仅当在浏览器中而不是在服务器中渲染angular 2通用应用程序时,才导入外部模块。

这个问题与某些依赖浏览器功能的PrimeNG模块有关,只能在浏览器中呈现。最好在服务器渲染时省略它们,因为日历和其他组件对于SEO并不真正重要。

目前,如果关闭服务器渲染,则可以渲染日历组件。但是,当我在app.module.ts中包含以下代码并打开服务器渲染时,服务器在button.js中产生错误“ ReferenceError:未定义事件”。

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

角度提供了一个isBrowser条件。

import { isBrowser } from 'angular2-universal';
Run Code Online (Sandbox Code Playgroud)

但是我不知道如何将其用于条件导入。是否真的有针对模块的方法?

Rod*_*ion 6

因此,有一种方法可以在浏览器中渲染PrimeNG组件,并在服务器渲染时忽略它们。这些问题帮助我开始寻找正确的方向:

angular-cli:使用环境变量进行条件导入

如何有条件导入ES6模块?

在服务器渲染时,我使用了模拟组件,该组件渲染一个简单的输入字段并使用相同的选择器“ p-calendar”。我最终在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
})
Run Code Online (Sandbox Code Playgroud)

为了使您的模拟组件支持[(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;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 问题是我想在app.module.ts中使用它。我不知道如何在其中注入PLATFORM_ID。isPlatformBrowser需要PLATFORM_ID才能工作。 (2认同)