Skip to content

Commit a12533a

Browse files
committed
refactor: use signals for all
1 parent f8b5fcd commit a12533a

28 files changed

+425
-559
lines changed

.github/workflows/nodejs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515

1616
strategy:
1717
matrix:
18-
node-version: ['20', '18.13.0']
18+
node-version: ['20', '18.19.1']
1919

2020
steps:
2121
- uses: actions/checkout@v4

apps/ngu-carousel-example/server.ts

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
import 'zone.js';
2-
31
import { APP_BASE_HREF } from '@angular/common';
42
import { CommonEngine } from '@angular/ssr';
53
import express from 'express';
6-
import { join } from 'node:path';
7-
import { AppServerModule } from './src/main.server';
4+
import { fileURLToPath } from 'node:url';
5+
import { dirname, join, resolve } from 'node:path';
6+
import bootstrap from './src/main.server';
87

98
// The Express app is exported so that it can be used by serverless Functions.
109
export function app(): express.Express {
1110
const server = express();
12-
const browserDistFolder = join(process.cwd(), 'dist/apps/ngu-carousel-example/browser');
13-
const pathToIndexHtml = join(browserDistFolder, 'index.html');
11+
const serverDistFolder = dirname(fileURLToPath(import.meta.url));
12+
const browserDistFolder = resolve(serverDistFolder, '../browser');
13+
const indexHtml = join(serverDistFolder, 'index.server.html');
1414

1515
const commonEngine = new CommonEngine();
1616

@@ -21,21 +21,23 @@ export function app(): express.Express {
2121
// server.get('/api/**', (req, res) => { });
2222
// Serve static files from /browser
2323
server.get(
24-
'*.*',
24+
'**',
2525
express.static(browserDistFolder, {
26-
maxAge: '1y'
26+
maxAge: '1y',
27+
index: 'index.html'
2728
})
2829
);
2930

3031
// All regular routes use the Angular engine
31-
server.get('*', (req, res, next) => {
32+
server.get('**', (req, res, next) => {
3233
const { protocol, originalUrl, baseUrl, headers } = req;
3334

3435
commonEngine
3536
.render({
36-
bootstrap: AppServerModule,
37-
documentFilePath: pathToIndexHtml,
37+
bootstrap,
38+
documentFilePath: indexHtml,
3839
url: `${protocol}://${headers.host}${originalUrl}`,
40+
publicPath: browserDistFolder,
3941
providers: [{ provide: APP_BASE_HREF, useValue: baseUrl }]
4042
})
4143
.then(html => res.send(html))
@@ -55,14 +57,4 @@ function run(): void {
5557
});
5658
}
5759

58-
// Webpack will replace 'require' with '__webpack_require__'
59-
// '__non_webpack_require__' is a proxy to Node 'require'
60-
// The below code is to ensure that the server is run only when not requiring the bundle.
61-
declare const __non_webpack_require__: NodeRequire;
62-
const mainModule = __non_webpack_require__.main;
63-
const moduleFilename = mainModule && mainModule.filename || '';
64-
if (moduleFilename === __filename || moduleFilename.includes('iisnode')) {
65-
run();
66-
}
67-
68-
export * from './src/main.server';
60+
run();
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { ApplicationConfig } from '@angular/core';
2-
import { provideAnimations } from '@angular/platform-browser/animations';
3-
import { provideRouter } from '@angular/router';
1+
import { mergeApplicationConfig, ApplicationConfig } from '@angular/core';
42
import { provideServerRendering } from '@angular/platform-server';
5-
import { APP_ROUTES } from './app.routes';
3+
import { appConfig } from './app.config';
64

7-
export const appServerConfig: ApplicationConfig = {
8-
providers: [provideRouter(APP_ROUTES), provideAnimations(), provideServerRendering()]
5+
const serverConfig: ApplicationConfig = {
6+
providers: [provideServerRendering()]
97
};
8+
9+
export const config = mergeApplicationConfig(appConfig, serverConfig);
Lines changed: 2 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,12 @@
1-
import {
2-
AfterViewInit,
3-
ChangeDetectionStrategy,
4-
ChangeDetectorRef,
5-
Component
6-
} from '@angular/core';
7-
import { NguCarouselConfig } from '@ngu/carousel';
8-
import { interval, Observable } from 'rxjs';
9-
import { map, startWith, take } from 'rxjs/operators';
10-
import { slider } from './slide-animation';
1+
import { ChangeDetectionStrategy, Component } from '@angular/core';
112
import { MainNavComponent } from './main-nav/main-nav.component';
123

134
@Component({
145
standalone: true,
156
selector: 'app-root',
167
templateUrl: './app.component.html',
178
styleUrls: ['./app.component.scss'],
18-
animations: [slider],
199
changeDetection: ChangeDetectionStrategy.OnPush,
2010
imports: [MainNavComponent]
2111
})
22-
export class AppComponent implements AfterViewInit {
23-
images = ['assets/bg.jpg', 'assets/car.png', 'assets/canberra.jpg', 'assets/holi.jpg'];
24-
25-
public carouselTileItems$: Observable<number[]>;
26-
public carouselTileConfig: NguCarouselConfig = {
27-
grid: { xs: 1, sm: 1, md: 1, lg: 5, all: 0 },
28-
speed: 250,
29-
point: {
30-
visible: true
31-
},
32-
touch: true,
33-
loop: true,
34-
interval: { timing: 1500 },
35-
animation: 'lazy'
36-
};
37-
tempData: any[];
38-
39-
constructor(private cdr: ChangeDetectorRef) {
40-
this.tempData = [];
41-
42-
this.carouselTileItems$ = interval(500).pipe(
43-
startWith(-1),
44-
take(30),
45-
map(() => {
46-
const data = (this.tempData = [
47-
...this.tempData,
48-
this.images[Math.floor(Math.random() * this.images.length)]
49-
]);
50-
51-
return data;
52-
})
53-
);
54-
}
55-
56-
ngAfterViewInit() {
57-
this.cdr.detectChanges();
58-
}
59-
}
12+
export class AppComponent {}

apps/ngu-carousel-example/src/app/banner-vertical/banner-vertical.component.html

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
<h2>Banner Vertical</h2>
2-
<ngu-carousel
3-
[inputs]="carouselBanner"
4-
[dataSource]="carouselTileItems$ | async"
5-
(onMove)="onmoveFn($event)"
6-
>
2+
<ngu-carousel [inputs]="carouselBanner" [dataSource]="items()" (onMove)="onmoveFn($event)">
73
<button NguCarouselPrev class="leftRs">&lt;</button>
84

95
<ngu-item *nguCarouselDef="let item; index as i; let ani = animate" [@slider]="ani">

apps/ngu-carousel-example/src/app/banner-vertical/banner-vertical.component.ts

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
import { ChangeDetectionStrategy, Component } from '@angular/core';
1+
import { ChangeDetectionStrategy, Component, afterNextRender, signal } from '@angular/core';
22
import { NguCarouselConfig } from '@ngu/carousel';
3-
import { interval, Observable } from 'rxjs';
4-
import { map, startWith, take } from 'rxjs/operators';
53
import { slider } from '../slide-animation';
6-
import { AsyncPipe } from '@angular/common';
74
import {
85
NguItemComponent,
96
NguCarouselPrevDirective,
@@ -24,8 +21,7 @@ import {
2421
NguCarouselPrevDirective,
2522
NguCarouselDefDirective,
2623
NguItemComponent,
27-
NguCarouselNextDirective,
28-
AsyncPipe
24+
NguCarouselNextDirective
2925
]
3026
})
3127
export class BannerVerticalComponent {
@@ -52,23 +48,23 @@ export class BannerVerticalComponent {
5248
};
5349
tempData: any[];
5450

55-
public carouselTileItems$: Observable<number[]>;
51+
public items = signal<string[]>([]);
5652

5753
constructor() {
58-
this.tempData = [];
59-
60-
this.carouselTileItems$ = interval(500).pipe(
61-
startWith(-1),
62-
take(30),
63-
map(() => {
64-
const data = (this.tempData = [
65-
...this.tempData,
66-
this.images[Math.floor(Math.random() * this.images.length)]
67-
]);
54+
this.addItem();
55+
afterNextRender(() => {
56+
const id = setInterval(() => {
57+
this.addItem();
58+
if (this.items().length >= 30) {
59+
clearInterval(id);
60+
}
61+
}, 500);
62+
});
63+
}
6864

69-
return data;
70-
})
71-
);
65+
addItem() {
66+
const i = Math.floor(Math.random() * this.images.length);
67+
this.items.update(items => [...items, this.images[i]]);
7268
}
7369

7470
/* It will be triggered on every slide*/

apps/ngu-carousel-example/src/app/banner/banner.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<h2>Banner</h2>
22
<ngu-carousel
33
[inputs]="carouselBanner"
4-
[dataSource]="carouselTileItems$ | async"
4+
[dataSource]="items()"
55
(onMove)="onmoveFn($event)"
66
[trackBy]="trackCarousel"
77
>

apps/ngu-carousel-example/src/app/banner/banner.component.ts

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
import { ChangeDetectionStrategy, Component } from '@angular/core';
1+
import { ChangeDetectionStrategy, Component, afterNextRender, signal } from '@angular/core';
22
import { NguCarouselConfig } from '@ngu/carousel';
3-
import { interval, Observable } from 'rxjs';
4-
import { map, startWith, take } from 'rxjs/operators';
53
import { slider } from '../slide-animation';
6-
import { AsyncPipe } from '@angular/common';
74
import {
85
NguItemComponent,
96
NguCarouselPrevDirective,
@@ -24,8 +21,7 @@ import {
2421
NguCarouselPrevDirective,
2522
NguCarouselDefDirective,
2623
NguItemComponent,
27-
NguCarouselNextDirective,
28-
AsyncPipe
24+
NguCarouselNextDirective
2925
]
3026
})
3127
export class BannerComponent {
@@ -52,23 +48,23 @@ export class BannerComponent {
5248
};
5349
tempData: any[];
5450

55-
public carouselTileItems$: Observable<number[]>;
51+
public items = signal<string[]>([]);
5652

5753
constructor() {
58-
this.tempData = [];
59-
60-
this.carouselTileItems$ = interval(500).pipe(
61-
startWith(-1),
62-
take(30),
63-
map(() => {
64-
const data = (this.tempData = [
65-
...this.tempData,
66-
this.images[Math.floor(Math.random() * this.images.length)]
67-
]);
54+
this.addItem();
55+
afterNextRender(() => {
56+
const id = setInterval(() => {
57+
this.addItem();
58+
if (this.items().length >= 30) {
59+
clearInterval(id);
60+
}
61+
}, 500);
62+
});
63+
}
6864

69-
return data;
70-
})
71-
);
65+
addItem() {
66+
const i = Math.floor(Math.random() * this.images.length);
67+
this.items.update(items => [...items, this.images[i]]);
7268
}
7369

7470
/* It will be triggered on every slide*/

apps/ngu-carousel-example/src/app/main-nav/main-nav.component.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
#drawer
44
class="sidenav"
55
fixedInViewport
6-
[attr.role]="(isHandset$ | async) ? 'dialog' : 'navigation'"
7-
[mode]="(isHandset$ | async) ? 'over' : 'side'"
8-
[opened]="(isHandset$ | async) === false"
6+
[attr.role]="isHandset() ? 'dialog' : 'navigation'"
7+
[mode]="isHandset() ? 'over' : 'side'"
8+
[opened]="isHandset() === false"
99
>
1010
<mat-toolbar>Banner Types</mat-toolbar>
1111
<mat-nav-list>
@@ -18,7 +18,7 @@
1818
</mat-sidenav>
1919
<mat-sidenav-content>
2020
<mat-toolbar color="primary">
21-
@if (isHandset$ | async) {
21+
@if (isHandset()) {
2222
<button type="button" aria-label="Toggle sidenav" mat-icon-button (click)="drawer.toggle()">
2323
<mat-icon aria-label="Side nav toggle icon">menu</mat-icon>
2424
</button>

apps/ngu-carousel-example/src/app/main-nav/main-nav.component.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
22
import { ChangeDetectionStrategy, Component } from '@angular/core';
3-
import { Observable } from 'rxjs';
4-
import { map, shareReplay } from 'rxjs/operators';
5-
import { AsyncPipe } from '@angular/common';
3+
import { toSignal } from '@angular/core/rxjs-interop';
64
import { MatIcon } from '@angular/material/icon';
75
import { MatIconButton, MatAnchor } from '@angular/material/button';
86
import { RouterLink, RouterOutlet } from '@angular/router';
97
import { MatNavList, MatListItem } from '@angular/material/list';
108
import { MatToolbar } from '@angular/material/toolbar';
119
import { MatSidenavContainer, MatSidenav, MatSidenavContent } from '@angular/material/sidenav';
10+
import { map } from 'rxjs';
1211

1312
@Component({
1413
standalone: true,
@@ -27,14 +26,12 @@ import { MatSidenavContainer, MatSidenav, MatSidenavContent } from '@angular/mat
2726
MatIconButton,
2827
MatIcon,
2928
MatAnchor,
30-
RouterOutlet,
31-
AsyncPipe
29+
RouterOutlet
3230
]
3331
})
3432
export class MainNavComponent {
35-
isHandset$: Observable<boolean> = this.breakpointObserver.observe(Breakpoints.Handset).pipe(
36-
map(result => result.matches),
37-
shareReplay()
33+
isHandset = toSignal(
34+
this.breakpointObserver.observe(Breakpoints.Handset).pipe(map(result => result.matches))
3835
);
3936

4037
constructor(private breakpointObserver: BreakpointObserver) {}

0 commit comments

Comments
 (0)