我使用默认的VS2017 15.4.2角度spa模板。当我添加fullcalendar我在加载时崩溃并出现错误: NodeInvocationException:由于错误导致预渲染失败:TypeError:无法设置未定义的属性'fullCalendar'当我使用fullcalendar-ag4时也是如此。 我的package.json:
import { Component, ViewChildrenDecorator, Input, Output, EventEmitter,
OnInit } from '@angular/core';
//import { Overlay } from 'angular2-modal'
import * as $ from 'jquery';
import * as moment from 'moment';
import 'fullcalendar';
import { Options } from "fullcalendar"
import * as _ from 'lodash';
import { IEvent } from '../interfaces/IEvent';
import { IEvents } from '../interfaces/IEvents';
declare var jQuery: any;
@Component({
selector: 'calendar',
templateUrl: 'calendar.component.html'
})
export class CalendarComponent implements OnInit {
@Input() public height: number;
@Input() public events: IEvents;
@Input() startDate: string;
@Output('event-click')
eventClick = new EventEmitter();
@Output('month-changed')
monthChanged = new EventEmitter();
@Output('date-change')
dateChange = new EventEmitter();
calElement;
addEvents(events: IEvents) {
this.calElement = $('#calendar');
if (!_.isNil(events)) {
$('#calendar').fullCalendar('addEventSource', this.events);
}
}
getCurrentMonth() {
const currentdate = <any>$("#calendar").fullCalendar('getDate');
return currentdate.month();
}
ngOnInit() {
this.calElement = $('#calendar');
let $this = this.calElement;
let clickFunc = function (calEvent, jsEvent, view) {
$this.eventClick.emit(calEvent);
};
let eventRender = function (event, element) {
const args = { event: event, view: element };
$this.dateChange.emit(args);
};
let viewRender = function (view, element) {
$this.monthChanged.emit(view.intervalStart.month());
};
let boundRender = eventRender.bind(this);
let boundClick = clickFunc.bind(this);
let boundView = viewRender.bind(this);
let options: any = {
locale: 'pl',
header: {
left: 'prev,next,today',
center: 'title',
right: 'month,basicWeek,basicDay'
},
defaultView: 'month',
aspectRatio: 1,
eventRender: boundRender,
eventClick: boundClick,
viewRender: boundView,
defaultDate: this.startDate ? this.startDate : Date.now()
};
if (this.height > 0) {
options.height = this.height;
}
this.calElement.fullCalendar(options);
this.addEvents(this.events);
}
}
calendar.component.ts
<div id='calendar'></div>
calendar.component.html
import { Component, OnInit, Input, Output } from '@angular/core';
import { IEvent } from '../shared/interfaces/IEvent';
import { IEvents } from '../shared/interfaces/IEvents';
import * as moment from 'moment';
@Component({
selector: 'report-calendar',
templateUrl: 'report-calendar.component.html'
})
export class ReportCalendarComponent implements OnInit {
@Input() events: Event[];
@Input() startDate: string;
ngOnInit() {
console.log('report-calendar: '+this.startDate);
}
ngOnChanges() {
}
}
报告-calendar.component.ts
<calendar></calendar>
报告-calendar.component.html
const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const merge = require('webpack-merge');
const treeShakableModules = [
'@angular/animations',
'@angular/common',
'@angular/compiler',
'@angular/core',
'@angular/forms',
'@angular/http',
'@angular/platform-browser',
'@angular/platform-browser-dynamic',
'@angular/router',
'zone.js',
];
const nonTreeShakableModules = [
'bootstrap',
'bootstrap/dist/css/bootstrap.css',
'es6-promise',
'es6-shim',
'event-source-polyfill',
'jquery',
'moment',
'fullcalendar/dist/fullcalendar.css',
'fullcalendar/dist/locale-all.js',
];
const allModules = treeShakableModules.concat(nonTreeShakableModules);
module.exports = (env) => {
const extractCSS = new ExtractTextPlugin('vendor.css');
const isDevBuild = !(env && env.prod);
const sharedConfig = {
stats: { modules: false },
resolve: { extensions: [ '.js' ] },
module: {
rules: [
{ test: /\.(png|woff|woff2|eot|ttf|svg)(\?|$)/, use: 'url- loader?limit=100000' }
]
},
output: {
publicPath: 'dist/',
filename: '[name].js',
library: '[name]_[hash]'
},
plugins: [
new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' }), // Maps these identifiers to the jQuery package (because Bootstrap expects it to be a global variable)
new webpack.ContextReplacementPlugin(/\@angular\b.*\b(bundles|linker)/, path.join(__dirname, './ClientApp')), // Workaround for https://github.com/angular/angular/issues/11580
new webpack.ContextReplacementPlugin(/angular(\\|\/)core(\\|\/)@angular/, path.join(__dirname, './ClientApp')), // Workaround for https://github.com/angular/angular/issues/14898
new webpack.IgnorePlugin(/^vertx$/) // Workaround for https://github.com/stefanpenner/es6-promise/issues/100
]
};
const clientBundleConfig = merge(sharedConfig, {
entry: {
// To keep development builds fast, include all vendor dependencies in the vendor bundle.
// But for production builds, leave the tree-shakable ones out so the AOT compiler can produce a smaller bundle.
vendor: isDevBuild ? allModules : nonTreeShakableModules
},
output: { path: path.join(__dirname, 'wwwroot', 'dist') },
module: {
rules: [
{ test: /\.css(\?|$)/, use: extractCSS.extract({ use: isDevBuild ? 'css-loader' : 'css-loader?minimize' }) }
]
},
plugins: [
extractCSS,
new webpack.DllPlugin({
path: path.join(__dirname, 'wwwroot', 'dist', '[name]-manifest.json'),
name: '[name]_[hash]'
})
].concat(isDevBuild ? [] : [
new webpack.optimize.UglifyJsPlugin()
])
});
const serverBundleConfig = merge(sharedConfig, {
target: 'node',
resolve: { mainFields: ['main'] },
entry: { vendor: allModules.concat(['aspnet-prerendering']) },
output: {
path: path.join(__dirname, 'ClientApp', 'dist'),
libraryTarget: 'commonjs2',
},
module: {
rules: [ { test: /\.css(\?|$)/, use: ['to-string-loader', isDevBuild ? 'css-loader' : 'css-loader?minimize' ] } ]
},
plugins: [
new webpack.DllPlugin({
path: path.join(__dirname, 'ClientApp', 'dist', '[name]-manifest.json'),
name: '[name]_[hash]'
})
]
});
return [clientBundleConfig, serverBundleConfig];
}
webpack.config.vendor.js
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { RouterModule } from '@angular/router';
import { AppComponent } from './components/app/app.component';
import { NavMenuComponent } from './components/navmenu/navmenu.component';
import { HomeComponent } from './components/home/home.component';
import { FetchDataComponent } from './components/fetchdata/fetchdata.component';
import { CounterComponent } from './components/counter/counter.component';
import { ReportCalendarComponent } from './components/calendar/report-calendar.component';
import { CalendarComponent } from './components/shared/calendar/calendar.component';
@NgModule({
declarations: [
AppComponent,
NavMenuComponent,
CounterComponent,
FetchDataComponent,
HomeComponent,
ReportCalendarComponent,
CalendarComponent
],
imports: [
CommonModule,
HttpModule,
FormsModule,
RouterModule.forRoot([
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'home', component: HomeComponent },
{ path: 'counter', component: CounterComponent },
{ path: 'fetch-data', component: FetchDataComponent },
{ path: 'calendar', component: ReportCalendarComponent },
{ path: '**', redirectTo: 'home' }
])
]
})
export class AppModuleShared {
}
app.module.shared.ts
NodeInvocationException: Prerendering failed because of error: TypeError: Cannot set property 'fullCalendar' of undefined
at Object.<anonymous> (C:\Projekty\Nauka\test2Fullcalendar\ClientApp\dist\main-server.js:16607:19)
at $.fullCalendar.version (C:\Projekty\Nauka\test2Fullcalendar\ClientApp\dist\main-server.js:16584:37)
at Object.module.exports (C:\Projekty\Nauka\test2Fullcalendar\ClientApp\dist\main-server.js:16593:3)
at __webpack_require__ (C:\Projekty\Nauka\test2Fullcalendar\ClientApp\dist\main-server.js:20:30)
at Object.<anonymous> (C:\Projekty\Nauka\test2Fullcalendar\ClientApp\dist\main-server.js:15475:71)
at __webpack_require__ (C:\Projekty\Nauka\test2Fullcalendar\ClientApp\dist\main-server.js:20:30)
at Object.<anonymous> (C:\Projekty\Nauka\test2Fullcalendar\ClientApp\dist\main-server.js:15412:106)
at __webpack_require__ (C:\Projekty\Nauka\test2Fullcalendar\ClientApp\dist\main-server.js:20:30)
at Object.hasOwn (C:\Projekty\Nauka\test2Fullcalendar\ClientApp\dist\main-server.js:14208:77)
at __webpack_require__ (C:\Projekty\Nauka\test2Fullcalendar\ClientApp\dist\main-server.js:20:30)
Current directory is: C:\Projekty\Nauka\test2Fullcalendar
更新
add