我一直试图在生产中将 ng-zorro-antd 日期选择器组件渲染到我的客户端中,但是每次我使用 ng serve --prod 渲染它时,我都会收到此错误:
ERROR Error: Uncaught (in promise): NullInjectorError: StaticInjectorError(AppModule)[CdkConnectedOverlay -> Overlay]:
StaticInjectorError(Platform: core)[CdkConnectedOverlay -> Overlay]:
NullInjectorError: No provider for Overlay!
NullInjectorError: StaticInjectorError(AppModule)[CdkConnectedOverlay -> Overlay]:
StaticInjectorError(Platform: core)[CdkConnectedOverlay -> Overlay]:
NullInjectorError: No provider for Overlay!
at NullInjector.push../node_modules/@angular/core/fesm5/core.js.NullInjector.get (core.js:1225)
at resolveToken (core.js:1463)
at tryResolveToken (core.js:1407)
at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (core.js:1311)
at resolveToken (core.js:1463)
at tryResolveToken (core.js:1407)
at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (core.js:1311)
at resolveNgModuleDep (core.js:18446)
at NgModuleRef_.push../node_modules/@angular/core/fesm5/core.js.NgModuleRef_.get (core.js:19135)
at resolveDep (core.js:19506)
at resolvePromise (zone.js:852)
at resolvePromise (zone.js:809)
at zone.js:913
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423)
at Object.onInvokeTask (core.js:24328)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:422)
at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:195)
at drainMicroTaskQueue (zone.js:601)
at push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask (zone.js:502)
at ZoneTask.invoke (zone.js:487)
我正在使用以下软件包运行此应用程序:
"name": "clocky-hub-client",
"version": "0.1.0-alpha.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@agm/core": "1.0.0-beta.5",
"@angular/animations": "8.0.0",
"@angular/cdk": "8.0.0",
"@angular/common": "8.0.0",
"@angular/compiler": "8.0.0",
"@angular/core": "8.0.0",
"@angular/forms": "8.0.0",
"@angular/http": "7.2.15",
"@angular/material": "^8.1.4",
"@angular/platform-browser": "8.0.0",
"@angular/platform-browser-dynamic": "8.0.0",
"@angular/router": "8.0.0",
"@asymmetrik/ngx-leaflet": "5.0.2",
"@fullcalendar/angular": "4.1.1",
"@fullcalendar/core": "4.1.0",
"@fullcalendar/daygrid": "4.1.0",
"@ng-bootstrap/ng-bootstrap": "^5.1.0",
"@ngrx/store": "7.4.0",
"@ngrx/store-devtools": "7.4.0",
"@swimlane/ngx-charts": "11.1.0",
"@types/jest": "^24.0.18",
"@types/jquery": "3.3.29",
"angular-particle": "^1.0.4",
"angular-particle-updated": "^1.0.4-1",
"animate.css": "3.7.1",
"chart.js": "2.8.0",
"core-js": "3.1.3",
"d3": "5.9.2",
"date-fns": "1.30.1",
"echarts": "4.2.1",
"echarts-gl": "1.1.1",
"highlight.js": "9.15.8",
"leaflet": "1.5.1",
"ng-zorro-antd": "7.4.1",
"ng2-charts": "2.2.4",
"ng2-dragula": "2.1.1",
"ngx-echarts": "4.1.1",
"ngx-highlightjs": "3.0.3",
"ngx-malihu-scrollbar": "7.0.0",
"particles.js": "2.0.0",
"rxjs": "6.5.2",
"tslib": "1.9.3",
"web-animations-js": "2.3.1",
"webpack-bundle-analyzer": "^3.4.1",
"zone.js": "0.9.1"
},
"devDependencies": {
"@angular-devkit/build-angular": "^0.800.0",
"@angular/cli": "8.0.0",
"@angular/compiler-cli": "8.0.0",
"@angular/language-service": "8.0.0",
"@types/jasmine": "3.3.13",
"@types/jasminewd2": "2.0.6",
"@types/node": "12.0.3",
"codelyzer": "5.0.1",
"jasmine-core": "3.4.0",
"jasmine-spec-reporter": "4.2.1",
"karma": "4.1.0",
"karma-chrome-launcher": "2.2.0",
"karma-coverage-istanbul-reporter": "2.0.5",
"karma-jasmine": "2.0.1",
"karma-jasmine-html-reporter": "1.4.2",
"node-sass": "4.12.0",
"protractor": "5.4.2",
"ts-node": "8.2.0",
"tslint": "5.16.0",
"typescript": "3.4.5"
}
}
编译选项是这样的:
src/tsconfig.app.json
{
"extends": "../tsconfig.json",
"typescript.tsdk": "./node_modules/typescript/lib",
"compilerOptions": {
"outDir": "../out-tsc/app",
"types": ["jest"],
"experimentalDecorators": true
},
"exclude": [
"test.ts",
"**/*.spect.ts"
]
}
src/tslint.json
{
"extends": "../tslint.json",
"rules": {
"directive-selector": [
true,
"attribute",
"tc",
"camelCase"
],
"component-selector": [
true,
"element",
"tc",
"kebab-case"
]
}
}
tsconfig.json
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"module": "es2015",
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es5",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2018",
"dom"
]
}
}
我像这样导入它:
src/app.module.ts:
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { HttpClientModule } from '@angular/common/http';
import { StoreModule } from '@ngrx/store';
import { ROUTES, RoutingModule } from './routing/routing.module';
import { AppComponent } from './app.component';
import { LayoutModule } from './layout/layout.module';
import { PagesModule } from './pages/pages.module';
import { UIModule } from './ui/ui.module';
import {OverlayModule} from '@angular/cdk/overlay';
import { pageDataReducer } from './store/reducers/page-data.reducer';
import { appSettingsReducer } from './store/reducers/app-settings.reducer';
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
import { environment } from '../environments/environment';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
LayoutModule,
HttpClientModule,
BrowserAnimationsModule,
RouterModule.forRoot(ROUTES, { useHash: true }),
StoreModule.forRoot({
pageData: pageDataReducer,
appSettings: appSettingsReducer,
}),
RoutingModule,
PagesModule,
UIModule,
OverlayModule,
StoreDevtoolsModule.instrument({ maxAge: 25, logOnly:
environment.production })
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
src/app/pages.module.ts:
...
import { NgZorroAntdModule } from 'ng-zorro-antd';
import { NZ_I18N, en_US } from 'ng-zorro-antd';
import { PageDatePickerComponent } from './ui/forms/date-picker/date-
picker.component';
...
@NgModule({
imports: [
CommonModule,
FormsModule,
ReactiveFormsModule,
RouterModule,
NgbModule,
ChartsModule,
NgxChartsModule,
NgxEchartsModule,
AgmCoreModule.forRoot({
apiKey: 'AIzaSyAbIFQ5ffgouATqs-sp8hgQf3zV4dTLzaU',
}),
LeafletModule,
NgZorroAntdModule,
HighlightModule.forRoot({ languages: hljsLanguages }),
FullCalendarModule,
UIModule,
LayoutModule,
],
declarations: [
...
PageDatePickerComponent
...
],
providers : [ { provide: NZ_I18N, useValue: en_US } ]
})
export class PagesModule { }
我在组件中这样使用它
src/app/pages/ui/forms/date-picker/date-picker.component.ts:
import { Component, OnInit, OnDestroy } from '@angular/core';
import * as getISOWeek from 'date-fns/get_iso_week';
import * as endOfMonth from 'date-fns/end_of_month';
import { en_US, zh_CN, NzI18nService } from 'ng-zorro-antd';
import { Store } from '@ngrx/store';
import { BasePageComponent } from '../../../base-page';
import { IAppState } from '../../../../interfaces/app-state';
import { HttpService } from '../../../../services/http/http.service';
@Component({
selector: 'page-date-picker',
templateUrl: './date-picker.component.html',
styleUrls: ['./date-picker.component.scss']
})
export class PageDatePickerComponent extends BasePageComponent implements OnInit, OnDestroy {
date = null;
startValue: Date | null;
endValue: Date | null;
endOpen: boolean;
isEnglish: boolean;
ranges: any;
dateMode: string;
plainFooter: string;
footerRender = () => 'extra footer';
constructor(
private i18n: NzI18nService,
store: Store<IAppState>,
httpSv: HttpService
) {
super(store, httpSv);
this.demoCode = `
<tc-form-group>
<nz-date-picker></nz-date-picker>
</tc-form-group>`;
this.pageData = {
title: 'Date picker',
loaded: true,
breadcrumbs: [
{
title: 'UI Kit',
route: 'dashboard'
},
{
title: 'Forms',
route: 'dashboard'
},
{
title: 'Date picker'
}
]
};
this.ranges = { Today: [new Date(), new Date()], 'This Month': [new Date(), endOfMonth(new Date())] };
this.startValue = null;
this.endValue = null;
this.endOpen = false;
this.isEnglish = true;
this.plainFooter = 'plain extra footer';
this.dateMode = 'time';
}
onChange(result: Date): void {
console.log('onChange: ', result);
}
getWeek(result: Date): void {
console.log('week: ', getISOWeek(result));
}
changeLanguage(): void {
this.i18n.setLocale(this.isEnglish ? zh_CN : en_US);
this.isEnglish = !this.isEnglish;
}
ngOnInit() {
super.ngOnInit();
}
ngOnDestroy() {
super.ngOnDestroy();
}
onStartChange(date: Date): void {
this.startValue = date;
}
onEndChange(date: Date): void {
this.endValue = date;
}
handleStartOpenChange(open: boolean): void {
if (!open) {
this.endOpen = true;
}
console.log('handleStartOpenChange', open, this.endOpen);
}
handleEndOpenChange(open: boolean): void {
console.log(open);
this.endOpen = open;
}
handleDateOpenChange(open: boolean): void {
if (open) {
this.dateMode = 'time';
}
}
handleDatePanelChange(mode: string): void {
console.log('handleDatePanelChange: ', mode);
}
onTimeChange(result: Date): void {
console.log('Selected Time: ', result);
}
onOk(result: Date): void {
console.log('onOk', result);
}
disabledStartDate = (startValue: Date): boolean => {
if (!startValue || !this.endValue) {
return false;
}
return startValue.getTime() > this.endValue.getTime();
};
disabledEndDate = (endValue: Date): boolean => {
if (!endValue || !this.startValue) {
return false;
}
return endValue.getTime() <= this.startValue.getTime();
};
}
src/app/pages/ui/forms/date-picker/date-picker.component.html:
<div class="col-12">
<tc-card [title]="'Range picker'">
<tc-form-group>
<nz-range-picker nzFormat="yyyy-MM-dd" (ngModelChange)="onChange($event)" nzShowTime></nz-range-picker>
</tc-form-group>
<tc-form-group class="mb-0">
<div class="elem-list">
<nz-date-picker
[nzDisabledDate]="disabledStartDate"
[nzFormat]="'yyyy-MM-dd'"
class="mr-4"
[(ngModel)]="startValue"
nzPlaceHolder="Start"
(ngModelChange)="onStartChange($event)"
(nzOnOpenChange)="handleStartOpenChange($event)"
></nz-date-picker>
<nz-date-picker
[nzDisabledDate]="disabledEndDate"
[nzFormat]="'yyyy-MM-dd'"
[(ngModel)]="endValue"
nzPlaceHolder="End"
[nzOpen]="endOpen"
(nzOnOpenChange)="handleEndOpenChange($event)"
(ngModelChange)="onEndChange($event)"
></nz-date-picker>
</div>
</tc-form-group>
</tc-card>
</div>
我正在使用带有 Angular 8 的 Ninet-NrGx 模板
它适用于开发模式而不是生产模式的事实让我非常好奇。
我尝试在 app.module 上导入 angular/cdk/overlay 模块,但没有成功。