Skip to content

Commit

Permalink
Refactor components to make compatible with Angular Universal
Browse files Browse the repository at this point in the history
  • Loading branch information
cetincakiroglu committed Mar 28, 2023
1 parent b6bedf6 commit 4f4ac27
Show file tree
Hide file tree
Showing 123 changed files with 14,595 additions and 2,026 deletions.
Empty file modified .browserslistrc
100755 → 100644
Empty file.
59 changes: 56 additions & 3 deletions angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"outputPath": "dist/primeng",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"polyfills": "zone.js",
"tsConfig": "tsconfig.app.json",
"aot": true,
"assets": [
Expand Down Expand Up @@ -127,7 +127,7 @@
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"polyfills": "zone.js",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"assets": [
Expand All @@ -141,6 +141,60 @@
"scripts": []
}
},
"server": {
"builder": "@angular-devkit/build-angular:server",
"options": {
"outputPath": "dist/primeng/server",
"main": "server.ts",
"tsConfig": "tsconfig.server.json",
"inlineStyleLanguage": "scss"
},
"configurations": {
"production": {
"outputHashing": "media"
},
"development": {
"optimization": false,
"sourceMap": true,
"extractLicenses": false,
"vendorChunk": true
}
},
"defaultConfiguration": "production"
},
"serve-ssr": {
"builder": "@nguniversal/builders:ssr-dev-server",
"configurations": {
"development": {
"browserTarget": "primeng:build:development",
"serverTarget": "primeng:server:development"
},
"production": {
"browserTarget": "primeng:build:production",
"serverTarget": "primeng:server:production"
}
},
"defaultConfiguration": "development"
},
"prerender": {
"builder": "@nguniversal/builders:prerender",
"options": {
"routes": [
"/"
]
},
"configurations": {
"production": {
"browserTarget": "primeng:build:production",
"serverTarget": "primeng:server:production"
},
"development": {
"browserTarget": "primeng:build:development",
"serverTarget": "primeng:server:development"
}
},
"defaultConfiguration": "production"
},
"lint": {
"builder": "@angular-eslint/builder:lint",
"options": {
Expand All @@ -153,7 +207,6 @@
}
}
},
"defaultProject": "primeng",
"cli": {
"analytics": false,
"schematicCollections": [
Expand Down
12 changes: 10 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@
"build:lib": "npm run build:check && npm run build:package",
"build:package": "BROWSERSLIST_ENV=library ng build primeng-library && gulp build-assets",
"build:check": "npm run format:check && npm run security:check && npm run test:headless",
"security:check": "npm audit --production --audit-level high"
"security:check": "npm audit --production --audit-level high",
"dev:ssr": "ng run primeng-ssr:serve-ssr",
"serve:ssr": "node dist/primeng-ssr/server/main.js",
"build:ssr": "ng build && ng run primeng-ssr:server",
"prerender": "ng run primeng-ssr:prerender"
},
"repository": {
"type": "git",
Expand All @@ -37,7 +41,11 @@
"@angular/forms": "^15.2.1",
"@angular/platform-browser": "^15.2.1",
"@angular/platform-browser-dynamic": "^15.2.1",
"@angular/platform-server": "^15.0.0",
"@angular/router": "^15.2.1",
"@nguniversal/common": "^15.2.0",
"@nguniversal/express-engine": "^15.2.0",
"@nguniversal/builders": "^15.2.0",
"@fullcalendar/angular": "^6.0.3",
"@fullcalendar/core": "^6.0.3",
"@fullcalendar/daygrid": "^6.0.3",
Expand Down Expand Up @@ -83,7 +91,7 @@
"tslib": "^2.3.0",
"typescript": "~4.8.4",
"xlsx": "^0.18.5",
"zone.js": "~0.11.4"
"zone.js": "~0.12.0"
},
"dependencies": {
"@docsearch/js": "^3.3.3",
Expand Down
86 changes: 86 additions & 0 deletions server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import 'zone.js/node';

import { APP_BASE_HREF } from '@angular/common';
import { ngExpressEngine } from '@nguniversal/express-engine';
import * as express from 'express';
import { existsSync } from 'fs';
import { join } from 'path';

import { AppServerModule } from './src/main.server';

// ssr DOM
const domino = require('domino');
const fs = require('fs');
const path = require('path');
// index from browser build!
const template = fs.readFileSync(path.join('.', 'dist/primeng-ssr/browser', 'index.html')).toString();
// for mock global window by domino
const win = domino.createWindow(template);
// mock
global['window'] = win;
// not implemented property and functions
Object.defineProperty(win.document.body.style, 'transform', {
value: () => {
return {
enumerable: true,
configurable: true,
};
},
});
// mock documnet
global['document'] = win.document;
// othres mock
global['CSS'] = null;
// global['XMLHttpRequest'] = require('xmlhttprequest').XMLHttpRequest;
global['Prism'] = null;

// The Express app is exported so that it can be used by serverless Functions.
export function app(): express.Express {
const server = express();
const distFolder = join(process.cwd(), 'dist/primeng-ssr/browser');
const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index';

// Our Universal express-engine (found @ https://github.com/angular/universal/tree/main/modules/express-engine)
server.engine('html', ngExpressEngine({
bootstrap: AppServerModule,
}));

server.set('view engine', 'html');
server.set('views', distFolder);

// Example Express Rest API endpoints
// server.get('/api/**', (req, res) => { });
// Serve static files from /browser
server.get('*.*', express.static(distFolder, {
maxAge: '1y'
}));

// All regular routes use the Universal engine
server.get('*', (req, res) => {
res.render(indexHtml, { req, providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }] });
});

return server;
}

function run(): void {
const port = process.env['PORT'] || 4000;

// Start up the Node server
const server = app();
server.listen(port, () => {
console.log(`Node Express server listening on http://localhost:${port}`);
});
}

// Webpack will replace 'require' with '__webpack_require__'
// '__non_webpack_require__' is a proxy to Node 'require'
// The below code is to ensure that the server is run only when not requiring the bundle.
declare const __non_webpack_require__: NodeRequire;
const mainModule = __non_webpack_require__.main;
const moduleFilename = mainModule && mainModule.filename || '';
if (moduleFilename === __filename || moduleFilename.includes('iisnode')) {
run();
}

export * from './src/main.server';
11 changes: 6 additions & 5 deletions src/app/components/carousel/carousel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@ import {
ChangeDetectorRef,
SimpleChanges,
Renderer2,
Inject
Inject,
PLATFORM_ID
} from '@angular/core';
import { PrimeTemplate, SharedModule, Header, Footer } from 'primeng/api';
import { RippleModule } from 'primeng/ripple';
import { CommonModule, DOCUMENT } from '@angular/common';
import { CommonModule, DOCUMENT, isPlatformBrowser } from '@angular/common';
import { UniqueComponentId } from 'primeng/utils';
import { DomHandler } from 'primeng/dom';

Expand Down Expand Up @@ -233,7 +234,7 @@ export class Carousel implements AfterContentInit {

window: Window;

constructor(public el: ElementRef, public zone: NgZone, public cd: ChangeDetectorRef, private renderer: Renderer2, @Inject(DOCUMENT) private document: Document) {
constructor(public el: ElementRef, public zone: NgZone, public cd: ChangeDetectorRef, private renderer: Renderer2, @Inject(DOCUMENT) private document: Document, @Inject(PLATFORM_ID) private platformId: any) {
this.totalShiftedItems = this.page * this.numScroll * -1;
this.window = this.document.defaultView as Window;
}
Expand Down Expand Up @@ -670,7 +671,7 @@ export class Carousel implements AfterContentInit {
}

bindDocumentListeners() {
if (DomHandler.isClient()) {
if (isPlatformBrowser(this.platformId)) {
if (!this.documentResizeListener) {
this.documentResizeListener = this.renderer.listen(this.window, 'resize', (event) => {
this.calculatePosition();
Expand All @@ -680,7 +681,7 @@ export class Carousel implements AfterContentInit {
}

unbindDocumentListeners() {
if (DomHandler.isClient()) {
if (isPlatformBrowser(this.platformId)) {
if (this.documentResizeListener) {
this.documentResizeListener();
this.documentResizeListener = null;
Expand Down
16 changes: 12 additions & 4 deletions src/app/components/colorpicker/colorpicker.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { NgModule, Component, ElementRef, Input, Output, OnDestroy, EventEmitter, forwardRef, Renderer2, ViewChild, ChangeDetectorRef, ChangeDetectionStrategy, ViewEncapsulation, Inject } from '@angular/core';
import { NgModule, Component, ElementRef, Input, Output, OnDestroy, EventEmitter, forwardRef, Renderer2, ViewChild, ChangeDetectorRef, ChangeDetectionStrategy, ViewEncapsulation, Inject, PLATFORM_ID } from '@angular/core';
import { trigger, state, style, transition, animate, AnimationEvent } from '@angular/animations';
import { CommonModule, DOCUMENT } from '@angular/common';
import { CommonModule, DOCUMENT, isPlatformBrowser } from '@angular/common';
import { DomHandler, ConnectedOverlayScrollHandler } from 'primeng/dom';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';
import { OverlayService, PrimeNGConfig } from 'primeng/api';
Expand Down Expand Up @@ -141,7 +141,15 @@ export class ColorPicker implements ControlValueAccessor, OnDestroy {

window: Window;

constructor(@Inject(DOCUMENT) private document: Document, public el: ElementRef, public renderer: Renderer2, public cd: ChangeDetectorRef, public config: PrimeNGConfig, public overlayService: OverlayService) {
constructor(
@Inject(DOCUMENT) private document: Document,
@Inject(PLATFORM_ID) private platformId: any,
public el: ElementRef,
public renderer: Renderer2,
public cd: ChangeDetectorRef,
public config: PrimeNGConfig,
public overlayService: OverlayService
) {
this.window = this.document.defaultView as Window;
}

Expand Down Expand Up @@ -517,7 +525,7 @@ export class ColorPicker implements ControlValueAccessor, OnDestroy {
}

bindDocumentResizeListener() {
if (DomHandler.isClient()) {
if (isPlatformBrowser(this.platformId)) {
this.documentResizeListener = this.renderer.listen(this.window, 'resize', this.onWindowResize.bind(this));
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/app/components/defer/defer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { NgModule, Directive, ElementRef, AfterViewInit, OnDestroy, TemplateRef, EmbeddedViewRef, ViewContainerRef, Renderer2, EventEmitter, Output, ContentChild, ChangeDetectorRef, Inject } from '@angular/core';
import { CommonModule, DOCUMENT } from '@angular/common';
import { NgModule, Directive, ElementRef, AfterViewInit, OnDestroy, TemplateRef, EmbeddedViewRef, ViewContainerRef, Renderer2, EventEmitter, Output, ContentChild, ChangeDetectorRef, Inject, PLATFORM_ID } from '@angular/core';
import { CommonModule, DOCUMENT, isPlatformBrowser } from '@angular/common';
import { DomHandler } from 'primeng/dom';

@Directive({
Expand All @@ -17,7 +17,7 @@ export class DeferredLoader implements AfterViewInit, OnDestroy {

view: EmbeddedViewRef<any>;

constructor(@Inject(DOCUMENT) private document: Document, public el: ElementRef, public renderer: Renderer2, public viewContainer: ViewContainerRef, private cd: ChangeDetectorRef) {}
constructor(@Inject(DOCUMENT) private document: Document, @Inject(PLATFORM_ID) private platformId: any, public el: ElementRef, public renderer: Renderer2, public viewContainer: ViewContainerRef, private cd: ChangeDetectorRef) {}

ngAfterViewInit() {
if (this.shouldLoad()) {
Expand Down Expand Up @@ -55,7 +55,7 @@ export class DeferredLoader implements AfterViewInit, OnDestroy {
}

isLoaded() {
return this.view != null && DomHandler.isClient();
return this.view != null && isPlatformBrowser(this.platformId);
}

ngOnDestroy() {
Expand Down
9 changes: 5 additions & 4 deletions src/app/components/dialog/dialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ import {
TemplateRef,
ContentChild,
OnInit,
Inject
Inject,
PLATFORM_ID
} from '@angular/core';
import { trigger, style, transition, animate, AnimationEvent, animation, useAnimation } from '@angular/animations';
import { CommonModule, DOCUMENT } from '@angular/common';
import { CommonModule, DOCUMENT, isPlatformBrowser } from '@angular/common';
import { DomHandler } from 'primeng/dom';
import { Header, Footer, SharedModule, PrimeTemplate, PrimeNGConfig } from 'primeng/api';
import { FocusTrapModule } from 'primeng/focustrap';
Expand Down Expand Up @@ -292,7 +293,7 @@ export class Dialog implements AfterContentInit, OnInit, OnDestroy {

private window: Window;

constructor(@Inject(DOCUMENT) private document: Document, public el: ElementRef, public renderer: Renderer2, public zone: NgZone, private cd: ChangeDetectorRef, public config: PrimeNGConfig) {
constructor(@Inject(DOCUMENT) private document: Document, @Inject(PLATFORM_ID) private platformId: any, public el: ElementRef, public renderer: Renderer2, public zone: NgZone, private cd: ChangeDetectorRef, public config: PrimeNGConfig) {
this.window = this.document.defaultView as Window;
}

Expand Down Expand Up @@ -445,7 +446,7 @@ export class Dialog implements AfterContentInit, OnInit, OnDestroy {
}

createStyle() {
if (DomHandler.isClient()) {
if (isPlatformBrowser(this.platformId)) {
if (!this.styleElement) {
this.styleElement = this.renderer.createElement('style');
this.styleElement.type = 'text/css';
Expand Down
4 changes: 3 additions & 1 deletion src/app/components/dom/domhandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,9 @@ export class DomHandler {
}

public static getUserAgent(): string {
return navigator.userAgent;
if (navigator && this.isClient()) {
return navigator.userAgent;
}
}

public static isIE() {
Expand Down
9 changes: 5 additions & 4 deletions src/app/components/dynamicdialog/dynamicdialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ export class DynamicDialogComponent implements AfterViewInit, OnDestroy {

constructor(
@Inject(DOCUMENT) private document: Document,
@Inject(PLATFORM_ID) private platformId: any,
private componentFactoryResolver: ComponentFactoryResolver,
private cd: ChangeDetectorRef,
public renderer: Renderer2,
Expand Down Expand Up @@ -479,15 +480,15 @@ export class DynamicDialogComponent implements AfterViewInit, OnDestroy {
}

bindDocumentDragListener() {
if (DomHandler.isClient()) {
if (isPlatformBrowser(this.platformId)) {
this.zone.runOutsideAngular(() => {
this.documentDragListener = this.renderer.listen(this.document, 'mousemove', this.onDrag.bind(this));
});
}
}

bindDocumentDragEndListener() {
if (DomHandler.isClient()) {
if (isPlatformBrowser(this.platformId)) {
this.zone.runOutsideAngular(() => {
this.documentDragEndListener = this.renderer.listen(this.document, 'mouseup', this.endDrag.bind(this));
});
Expand All @@ -509,7 +510,7 @@ export class DynamicDialogComponent implements AfterViewInit, OnDestroy {
}

bindDocumentResizeListeners() {
if (DomHandler.isClient()) {
if (isPlatformBrowser(this.platformId)) {
this.zone.runOutsideAngular(() => {
this.documentResizeListener = this.renderer.listen(this.document, 'mousemove', this.onResize.bind(this));
this.documentResizeEndListener = this.renderer.listen(this.document, 'mouseup', this.resizeEnd.bind(this));
Expand Down Expand Up @@ -552,7 +553,7 @@ export class DynamicDialogComponent implements AfterViewInit, OnDestroy {
}

bindDocumentKeydownListener() {
if (DomHandler.isClient()) {
if (isPlatformBrowser(this.platformId)) {
this.zone.runOutsideAngular(() => {
this.documentKeydownListener = this.renderer.listen(this.document, 'keydown', this.onKeydown.bind(this));
});
Expand Down
Loading

0 comments on commit 4f4ac27

Please sign in to comment.