ngxsmk-datepicker 2.3.1 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +942 -922
- package/docs/API.md +2423 -2413
- package/docs/COMPATIBILITY.md +471 -471
- package/docs/INTEGRATION.md +703 -703
- package/docs/IONIC_INTEGRATION.md +228 -228
- package/docs/LOCALE-GUIDE.md +300 -300
- package/docs/PLUGIN-ARCHITECTURE.md +930 -930
- package/docs/SSR-EXAMPLE.md +427 -427
- package/docs/THEME-TOKENS.md +324 -324
- package/docs/TIMEZONE.md +307 -307
- package/docs/extension-points.md +419 -419
- package/docs/signal-forms.md +600 -600
- package/docs/signals.md +266 -266
- package/docs/ssr.md +305 -305
- package/package.json +106 -104
- package/schematics/collection.json +10 -0
- package/schematics/ng-add/schema.json +14 -0
- package/schematics/tsconfig.json +17 -0
- package/CHANGELOG.md +0 -1246
- package/LICENSE +0 -21
- package/MIGRATION.md +0 -1794
- package/docs/FEATURE_SCOPING.md +0 -60
- package/docs/IONIC_TESTING.md +0 -148
- package/docs/REFACTOR_PLAN.md +0 -38
- package/docs/SEO.md +0 -214
- package/fesm2022/ngxsmk-datepicker.mjs +0 -14693
- package/types/ngxsmk-datepicker.d.ts +0 -2489
package/docs/ssr.md
CHANGED
|
@@ -1,305 +1,305 @@
|
|
|
1
|
-
# Server-Side Rendering (SSR) Guide
|
|
2
|
-
|
|
3
|
-
**Last updated:**
|
|
4
|
-
|
|
5
|
-
ngxsmk-datepicker is fully compatible with Angular Universal and server-side rendering. This guide covers SSR setup, best practices, and troubleshooting.
|
|
6
|
-
|
|
7
|
-
## Overview
|
|
8
|
-
|
|
9
|
-
The datepicker is designed to work seamlessly in both server and browser environments:
|
|
10
|
-
|
|
11
|
-
- ✅ All browser-only APIs are guarded with platform checks
|
|
12
|
-
- ✅ No direct `window` or `document` access during initialization
|
|
13
|
-
- ✅ Event listeners only attach in browser environment
|
|
14
|
-
- ✅ Compatible with Angular Universal
|
|
15
|
-
- ✅ Supports partial hydration
|
|
16
|
-
|
|
17
|
-
## Basic SSR Setup
|
|
18
|
-
|
|
19
|
-
### Angular Universal Installation
|
|
20
|
-
|
|
21
|
-
If you haven't set up Angular Universal yet:
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
ng add @nguniversal/express-engine
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
### No Additional Configuration Required
|
|
28
|
-
|
|
29
|
-
The datepicker works out of the box with SSR. No special configuration is needed:
|
|
30
|
-
|
|
31
|
-
```typescript
|
|
32
|
-
import { Component } from '@angular/core';
|
|
33
|
-
import { NgxsmkDatepickerComponent } from 'ngxsmk-datepicker';
|
|
34
|
-
|
|
35
|
-
@Component({
|
|
36
|
-
selector: 'app-root',
|
|
37
|
-
standalone: true,
|
|
38
|
-
imports: [NgxsmkDatepickerComponent],
|
|
39
|
-
template: `
|
|
40
|
-
<ngxsmk-datepicker
|
|
41
|
-
mode="single"
|
|
42
|
-
[value]="selectedDate">
|
|
43
|
-
</ngxsmk-datepicker>
|
|
44
|
-
`
|
|
45
|
-
})
|
|
46
|
-
export class AppComponent {
|
|
47
|
-
selectedDate: Date | null = null;
|
|
48
|
-
}
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
## Platform Detection
|
|
52
|
-
|
|
53
|
-
The datepicker automatically detects the platform and only uses browser APIs when available:
|
|
54
|
-
|
|
55
|
-
```typescript
|
|
56
|
-
// Internal implementation (you don't need to do this)
|
|
57
|
-
private readonly isBrowser = isPlatformBrowser(this.platformId);
|
|
58
|
-
|
|
59
|
-
// Browser-only code is automatically guarded
|
|
60
|
-
if (this.isBrowser) {
|
|
61
|
-
// Safe to use window, document, etc.
|
|
62
|
-
}
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
## SSR Best Practices
|
|
66
|
-
|
|
67
|
-
### 1. Initialize Values Safely
|
|
68
|
-
|
|
69
|
-
Always initialize date values safely:
|
|
70
|
-
|
|
71
|
-
```typescript
|
|
72
|
-
import { Component, PLATFORM_ID, inject } from '@angular/core';
|
|
73
|
-
import { isPlatformBrowser } from '@angular/common';
|
|
74
|
-
|
|
75
|
-
@Component({
|
|
76
|
-
// ...
|
|
77
|
-
})
|
|
78
|
-
export class SafeComponent {
|
|
79
|
-
private platformId = inject(PLATFORM_ID);
|
|
80
|
-
|
|
81
|
-
selectedDate: Date | null = null;
|
|
82
|
-
|
|
83
|
-
ngOnInit() {
|
|
84
|
-
// Only access browser APIs in browser
|
|
85
|
-
if (isPlatformBrowser(this.platformId)) {
|
|
86
|
-
this.selectedDate = new Date();
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
### 2. Use Signals for Reactive Data
|
|
93
|
-
|
|
94
|
-
Signals work great with SSR:
|
|
95
|
-
|
|
96
|
-
```typescript
|
|
97
|
-
import { Component, signal } from '@angular/core';
|
|
98
|
-
|
|
99
|
-
@Component({
|
|
100
|
-
// ...
|
|
101
|
-
})
|
|
102
|
-
export class SignalComponent {
|
|
103
|
-
// Signals are SSR-safe
|
|
104
|
-
selectedDate = signal<Date | null>(null);
|
|
105
|
-
}
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
### 3. Server-Side Data
|
|
109
|
-
|
|
110
|
-
When fetching data on the server:
|
|
111
|
-
|
|
112
|
-
```typescript
|
|
113
|
-
import { Component, inject } from '@angular/core';
|
|
114
|
-
import { HttpClient } from '@angular/common/http';
|
|
115
|
-
import { httpResource } from '@angular/common/http';
|
|
116
|
-
import { signal, linkedSignal, computed } from '@angular/core';
|
|
117
|
-
|
|
118
|
-
@Component({
|
|
119
|
-
// ...
|
|
120
|
-
})
|
|
121
|
-
export class ServerDataComponent {
|
|
122
|
-
private http = inject(HttpClient);
|
|
123
|
-
|
|
124
|
-
resource = httpResource({
|
|
125
|
-
request: () => this.http.get<{ date: string }>('/api/data'),
|
|
126
|
-
loader: signal(false)
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
localObject = linkedSignal(() => this.resource.response.value());
|
|
130
|
-
|
|
131
|
-
// Computed signals are SSR-safe
|
|
132
|
-
selectedDate = computed(() => {
|
|
133
|
-
const obj = this.localObject();
|
|
134
|
-
return obj?.date ? new Date(obj.date) : null;
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
## Testing SSR
|
|
140
|
-
|
|
141
|
-
### Build for SSR
|
|
142
|
-
|
|
143
|
-
```bash
|
|
144
|
-
npm run build:ssr
|
|
145
|
-
npm run serve:ssr
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
### Verify SSR Works
|
|
149
|
-
|
|
150
|
-
1. Build your app with SSR
|
|
151
|
-
2. Check the server-rendered HTML contains the datepicker markup
|
|
152
|
-
3. Verify no console errors during server rendering
|
|
153
|
-
4. Test that the datepicker works after hydration
|
|
154
|
-
|
|
155
|
-
## Common SSR Issues
|
|
156
|
-
|
|
157
|
-
### Issue: Datepicker not rendering on server
|
|
158
|
-
|
|
159
|
-
**Solution**: Ensure you're using the component correctly. The datepicker renders its initial state on the server, but interactive features (like opening the calendar) only work in the browser.
|
|
160
|
-
|
|
161
|
-
### Issue: `window is not defined` error
|
|
162
|
-
|
|
163
|
-
**Solution**: This shouldn't happen with the current version. If you see this error, ensure you're using the latest version of the datepicker. All browser APIs are properly guarded.
|
|
164
|
-
|
|
165
|
-
### Issue: Dates not displaying correctly
|
|
166
|
-
|
|
167
|
-
**Solution**: Ensure date values are properly serialized/deserialized. Use `Date` objects, not strings, when possible:
|
|
168
|
-
|
|
169
|
-
```typescript
|
|
170
|
-
// ❌ Bad - may cause issues
|
|
171
|
-
date: "2024-01-15"
|
|
172
|
-
|
|
173
|
-
// ✅ Good
|
|
174
|
-
date: new Date("2024-01-15")
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
### Issue: Locale not working on server
|
|
178
|
-
|
|
179
|
-
**Solution**: The datepicker uses the browser's locale by default. On the server, you may need to explicitly set the locale:
|
|
180
|
-
|
|
181
|
-
```html
|
|
182
|
-
<ngxsmk-datepicker
|
|
183
|
-
[locale]="'en-US'"
|
|
184
|
-
mode="single">
|
|
185
|
-
</ngxsmk-datepicker>
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
Or inject `LOCALE_ID`:
|
|
189
|
-
|
|
190
|
-
```typescript
|
|
191
|
-
import { LOCALE_ID, inject } from '@angular/core';
|
|
192
|
-
|
|
193
|
-
@Component({
|
|
194
|
-
// ...
|
|
195
|
-
providers: [
|
|
196
|
-
{ provide: LOCALE_ID, useValue: 'en-US' }
|
|
197
|
-
]
|
|
198
|
-
})
|
|
199
|
-
export class LocaleComponent {
|
|
200
|
-
locale = inject(LOCALE_ID);
|
|
201
|
-
}
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
## Hydration
|
|
205
|
-
|
|
206
|
-
The datepicker supports Angular's partial hydration:
|
|
207
|
-
|
|
208
|
-
1. The component renders on the server
|
|
209
|
-
2. On client hydration, interactive features become available
|
|
210
|
-
3. No additional configuration needed
|
|
211
|
-
|
|
212
|
-
## Performance Considerations
|
|
213
|
-
|
|
214
|
-
### OnPush Change Detection
|
|
215
|
-
|
|
216
|
-
The datepicker uses `OnPush` change detection, which is optimal for SSR:
|
|
217
|
-
|
|
218
|
-
- Fewer change detection cycles
|
|
219
|
-
- Better performance in both server and browser
|
|
220
|
-
- Compatible with zoneless applications
|
|
221
|
-
|
|
222
|
-
### Lazy Initialization
|
|
223
|
-
|
|
224
|
-
Browser-only features are lazily initialized:
|
|
225
|
-
|
|
226
|
-
- Event listeners attach only in browser
|
|
227
|
-
- Media queries only checked in browser
|
|
228
|
-
- Navigator API only accessed in browser
|
|
229
|
-
|
|
230
|
-
## Zone.js and Zoneless
|
|
231
|
-
|
|
232
|
-
The datepicker works with or without Zone.js:
|
|
233
|
-
|
|
234
|
-
- ✅ Works with Zone.js (default)
|
|
235
|
-
- ✅ Works without Zone.js (zoneless)
|
|
236
|
-
- Uses `ChangeDetectorRef.markForCheck()` for manual change detection
|
|
237
|
-
- Compatible with Angular's zoneless mode
|
|
238
|
-
|
|
239
|
-
## Example: Full SSR Setup
|
|
240
|
-
|
|
241
|
-
```typescript
|
|
242
|
-
import { Component, signal, inject } from '@angular/core';
|
|
243
|
-
import { HttpClient } from '@angular/common/http';
|
|
244
|
-
import { httpResource } from '@angular/common/http';
|
|
245
|
-
import { linkedSignal, computed } from '@angular/core';
|
|
246
|
-
import { NgxsmkDatepickerComponent } from 'ngxsmk-datepicker';
|
|
247
|
-
|
|
248
|
-
@Component({
|
|
249
|
-
selector: 'app-ssr-example',
|
|
250
|
-
standalone: true,
|
|
251
|
-
imports: [NgxsmkDatepickerComponent],
|
|
252
|
-
template: `
|
|
253
|
-
<ngxsmk-datepicker
|
|
254
|
-
[value]="selectedDate()"
|
|
255
|
-
(valueChange)="onDateChange($event)"
|
|
256
|
-
mode="single"
|
|
257
|
-
placeholder="Select a date">
|
|
258
|
-
</ngxsmk-datepicker>
|
|
259
|
-
`
|
|
260
|
-
})
|
|
261
|
-
export class SSRExampleComponent {
|
|
262
|
-
private http = inject(HttpClient);
|
|
263
|
-
|
|
264
|
-
// Fetch data (works on both server and client)
|
|
265
|
-
resource = httpResource({
|
|
266
|
-
request: () => this.http.get<{ date: string }>('/api/data'),
|
|
267
|
-
loader: signal(false)
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
// Link to response
|
|
271
|
-
localObject = linkedSignal(() => this.resource.response.value());
|
|
272
|
-
|
|
273
|
-
// Compute date (SSR-safe)
|
|
274
|
-
selectedDate = computed(() => {
|
|
275
|
-
const obj = this.localObject();
|
|
276
|
-
return obj?.date ? new Date(obj.date) : null;
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
onDateChange(date: Date | null) {
|
|
280
|
-
// Update logic here
|
|
281
|
-
console.log('Date changed:', date);
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
```
|
|
285
|
-
|
|
286
|
-
## Troubleshooting Checklist
|
|
287
|
-
|
|
288
|
-
- [ ] Build completes without errors: `npm run build:ssr`
|
|
289
|
-
- [ ] Server starts without errors: `npm run serve:ssr`
|
|
290
|
-
- [ ] No `window is not defined` errors in server logs
|
|
291
|
-
- [ ] Datepicker renders in server HTML
|
|
292
|
-
- [ ] Datepicker works after client hydration
|
|
293
|
-
- [ ] No console errors in browser
|
|
294
|
-
- [ ] Dates display correctly
|
|
295
|
-
- [ ] Locale works as expected
|
|
296
|
-
|
|
297
|
-
## Additional Resources
|
|
298
|
-
|
|
299
|
-
- **[SSR Example](./SSR-EXAMPLE.md)** - Complete working example with code samples
|
|
300
|
-
- [Angular Universal Guide](https://angular.dev/guide/ssr)
|
|
301
|
-
- [Angular SSR Documentation](https://angular.dev/guide/ssr)
|
|
302
|
-
- [Platform Detection](https://angular.dev/api/common/isPlatformBrowser)
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
1
|
+
# Server-Side Rendering (SSR) Guide
|
|
2
|
+
|
|
3
|
+
**Last updated:** July 2, 2026 - **Current stable:** v2.4.0
|
|
4
|
+
|
|
5
|
+
ngxsmk-datepicker is fully compatible with Angular Universal and server-side rendering. This guide covers SSR setup, best practices, and troubleshooting.
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
The datepicker is designed to work seamlessly in both server and browser environments:
|
|
10
|
+
|
|
11
|
+
- ✅ All browser-only APIs are guarded with platform checks
|
|
12
|
+
- ✅ No direct `window` or `document` access during initialization
|
|
13
|
+
- ✅ Event listeners only attach in browser environment
|
|
14
|
+
- ✅ Compatible with Angular Universal
|
|
15
|
+
- ✅ Supports partial hydration
|
|
16
|
+
|
|
17
|
+
## Basic SSR Setup
|
|
18
|
+
|
|
19
|
+
### Angular Universal Installation
|
|
20
|
+
|
|
21
|
+
If you haven't set up Angular Universal yet:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
ng add @nguniversal/express-engine
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### No Additional Configuration Required
|
|
28
|
+
|
|
29
|
+
The datepicker works out of the box with SSR. No special configuration is needed:
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import { Component } from '@angular/core';
|
|
33
|
+
import { NgxsmkDatepickerComponent } from 'ngxsmk-datepicker';
|
|
34
|
+
|
|
35
|
+
@Component({
|
|
36
|
+
selector: 'app-root',
|
|
37
|
+
standalone: true,
|
|
38
|
+
imports: [NgxsmkDatepickerComponent],
|
|
39
|
+
template: `
|
|
40
|
+
<ngxsmk-datepicker
|
|
41
|
+
mode="single"
|
|
42
|
+
[value]="selectedDate">
|
|
43
|
+
</ngxsmk-datepicker>
|
|
44
|
+
`
|
|
45
|
+
})
|
|
46
|
+
export class AppComponent {
|
|
47
|
+
selectedDate: Date | null = null;
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Platform Detection
|
|
52
|
+
|
|
53
|
+
The datepicker automatically detects the platform and only uses browser APIs when available:
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
// Internal implementation (you don't need to do this)
|
|
57
|
+
private readonly isBrowser = isPlatformBrowser(this.platformId);
|
|
58
|
+
|
|
59
|
+
// Browser-only code is automatically guarded
|
|
60
|
+
if (this.isBrowser) {
|
|
61
|
+
// Safe to use window, document, etc.
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## SSR Best Practices
|
|
66
|
+
|
|
67
|
+
### 1. Initialize Values Safely
|
|
68
|
+
|
|
69
|
+
Always initialize date values safely:
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
import { Component, PLATFORM_ID, inject } from '@angular/core';
|
|
73
|
+
import { isPlatformBrowser } from '@angular/common';
|
|
74
|
+
|
|
75
|
+
@Component({
|
|
76
|
+
// ...
|
|
77
|
+
})
|
|
78
|
+
export class SafeComponent {
|
|
79
|
+
private platformId = inject(PLATFORM_ID);
|
|
80
|
+
|
|
81
|
+
selectedDate: Date | null = null;
|
|
82
|
+
|
|
83
|
+
ngOnInit() {
|
|
84
|
+
// Only access browser APIs in browser
|
|
85
|
+
if (isPlatformBrowser(this.platformId)) {
|
|
86
|
+
this.selectedDate = new Date();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### 2. Use Signals for Reactive Data
|
|
93
|
+
|
|
94
|
+
Signals work great with SSR:
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
import { Component, signal } from '@angular/core';
|
|
98
|
+
|
|
99
|
+
@Component({
|
|
100
|
+
// ...
|
|
101
|
+
})
|
|
102
|
+
export class SignalComponent {
|
|
103
|
+
// Signals are SSR-safe
|
|
104
|
+
selectedDate = signal<Date | null>(null);
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### 3. Server-Side Data
|
|
109
|
+
|
|
110
|
+
When fetching data on the server:
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
import { Component, inject } from '@angular/core';
|
|
114
|
+
import { HttpClient } from '@angular/common/http';
|
|
115
|
+
import { httpResource } from '@angular/common/http';
|
|
116
|
+
import { signal, linkedSignal, computed } from '@angular/core';
|
|
117
|
+
|
|
118
|
+
@Component({
|
|
119
|
+
// ...
|
|
120
|
+
})
|
|
121
|
+
export class ServerDataComponent {
|
|
122
|
+
private http = inject(HttpClient);
|
|
123
|
+
|
|
124
|
+
resource = httpResource({
|
|
125
|
+
request: () => this.http.get<{ date: string }>('/api/data'),
|
|
126
|
+
loader: signal(false)
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
localObject = linkedSignal(() => this.resource.response.value());
|
|
130
|
+
|
|
131
|
+
// Computed signals are SSR-safe
|
|
132
|
+
selectedDate = computed(() => {
|
|
133
|
+
const obj = this.localObject();
|
|
134
|
+
return obj?.date ? new Date(obj.date) : null;
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Testing SSR
|
|
140
|
+
|
|
141
|
+
### Build for SSR
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
npm run build:ssr
|
|
145
|
+
npm run serve:ssr
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Verify SSR Works
|
|
149
|
+
|
|
150
|
+
1. Build your app with SSR
|
|
151
|
+
2. Check the server-rendered HTML contains the datepicker markup
|
|
152
|
+
3. Verify no console errors during server rendering
|
|
153
|
+
4. Test that the datepicker works after hydration
|
|
154
|
+
|
|
155
|
+
## Common SSR Issues
|
|
156
|
+
|
|
157
|
+
### Issue: Datepicker not rendering on server
|
|
158
|
+
|
|
159
|
+
**Solution**: Ensure you're using the component correctly. The datepicker renders its initial state on the server, but interactive features (like opening the calendar) only work in the browser.
|
|
160
|
+
|
|
161
|
+
### Issue: `window is not defined` error
|
|
162
|
+
|
|
163
|
+
**Solution**: This shouldn't happen with the current version. If you see this error, ensure you're using the latest version of the datepicker. All browser APIs are properly guarded.
|
|
164
|
+
|
|
165
|
+
### Issue: Dates not displaying correctly
|
|
166
|
+
|
|
167
|
+
**Solution**: Ensure date values are properly serialized/deserialized. Use `Date` objects, not strings, when possible:
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
// ❌ Bad - may cause issues
|
|
171
|
+
date: "2024-01-15"
|
|
172
|
+
|
|
173
|
+
// ✅ Good
|
|
174
|
+
date: new Date("2024-01-15")
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Issue: Locale not working on server
|
|
178
|
+
|
|
179
|
+
**Solution**: The datepicker uses the browser's locale by default. On the server, you may need to explicitly set the locale:
|
|
180
|
+
|
|
181
|
+
```html
|
|
182
|
+
<ngxsmk-datepicker
|
|
183
|
+
[locale]="'en-US'"
|
|
184
|
+
mode="single">
|
|
185
|
+
</ngxsmk-datepicker>
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Or inject `LOCALE_ID`:
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
import { LOCALE_ID, inject } from '@angular/core';
|
|
192
|
+
|
|
193
|
+
@Component({
|
|
194
|
+
// ...
|
|
195
|
+
providers: [
|
|
196
|
+
{ provide: LOCALE_ID, useValue: 'en-US' }
|
|
197
|
+
]
|
|
198
|
+
})
|
|
199
|
+
export class LocaleComponent {
|
|
200
|
+
locale = inject(LOCALE_ID);
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Hydration
|
|
205
|
+
|
|
206
|
+
The datepicker supports Angular's partial hydration:
|
|
207
|
+
|
|
208
|
+
1. The component renders on the server
|
|
209
|
+
2. On client hydration, interactive features become available
|
|
210
|
+
3. No additional configuration needed
|
|
211
|
+
|
|
212
|
+
## Performance Considerations
|
|
213
|
+
|
|
214
|
+
### OnPush Change Detection
|
|
215
|
+
|
|
216
|
+
The datepicker uses `OnPush` change detection, which is optimal for SSR:
|
|
217
|
+
|
|
218
|
+
- Fewer change detection cycles
|
|
219
|
+
- Better performance in both server and browser
|
|
220
|
+
- Compatible with zoneless applications
|
|
221
|
+
|
|
222
|
+
### Lazy Initialization
|
|
223
|
+
|
|
224
|
+
Browser-only features are lazily initialized:
|
|
225
|
+
|
|
226
|
+
- Event listeners attach only in browser
|
|
227
|
+
- Media queries only checked in browser
|
|
228
|
+
- Navigator API only accessed in browser
|
|
229
|
+
|
|
230
|
+
## Zone.js and Zoneless
|
|
231
|
+
|
|
232
|
+
The datepicker works with or without Zone.js:
|
|
233
|
+
|
|
234
|
+
- ✅ Works with Zone.js (default)
|
|
235
|
+
- ✅ Works without Zone.js (zoneless)
|
|
236
|
+
- Uses `ChangeDetectorRef.markForCheck()` for manual change detection
|
|
237
|
+
- Compatible with Angular's zoneless mode
|
|
238
|
+
|
|
239
|
+
## Example: Full SSR Setup
|
|
240
|
+
|
|
241
|
+
```typescript
|
|
242
|
+
import { Component, signal, inject } from '@angular/core';
|
|
243
|
+
import { HttpClient } from '@angular/common/http';
|
|
244
|
+
import { httpResource } from '@angular/common/http';
|
|
245
|
+
import { linkedSignal, computed } from '@angular/core';
|
|
246
|
+
import { NgxsmkDatepickerComponent } from 'ngxsmk-datepicker';
|
|
247
|
+
|
|
248
|
+
@Component({
|
|
249
|
+
selector: 'app-ssr-example',
|
|
250
|
+
standalone: true,
|
|
251
|
+
imports: [NgxsmkDatepickerComponent],
|
|
252
|
+
template: `
|
|
253
|
+
<ngxsmk-datepicker
|
|
254
|
+
[value]="selectedDate()"
|
|
255
|
+
(valueChange)="onDateChange($event)"
|
|
256
|
+
mode="single"
|
|
257
|
+
placeholder="Select a date">
|
|
258
|
+
</ngxsmk-datepicker>
|
|
259
|
+
`
|
|
260
|
+
})
|
|
261
|
+
export class SSRExampleComponent {
|
|
262
|
+
private http = inject(HttpClient);
|
|
263
|
+
|
|
264
|
+
// Fetch data (works on both server and client)
|
|
265
|
+
resource = httpResource({
|
|
266
|
+
request: () => this.http.get<{ date: string }>('/api/data'),
|
|
267
|
+
loader: signal(false)
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
// Link to response
|
|
271
|
+
localObject = linkedSignal(() => this.resource.response.value());
|
|
272
|
+
|
|
273
|
+
// Compute date (SSR-safe)
|
|
274
|
+
selectedDate = computed(() => {
|
|
275
|
+
const obj = this.localObject();
|
|
276
|
+
return obj?.date ? new Date(obj.date) : null;
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
onDateChange(date: Date | null) {
|
|
280
|
+
// Update logic here
|
|
281
|
+
console.log('Date changed:', date);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
## Troubleshooting Checklist
|
|
287
|
+
|
|
288
|
+
- [ ] Build completes without errors: `npm run build:ssr`
|
|
289
|
+
- [ ] Server starts without errors: `npm run serve:ssr`
|
|
290
|
+
- [ ] No `window is not defined` errors in server logs
|
|
291
|
+
- [ ] Datepicker renders in server HTML
|
|
292
|
+
- [ ] Datepicker works after client hydration
|
|
293
|
+
- [ ] No console errors in browser
|
|
294
|
+
- [ ] Dates display correctly
|
|
295
|
+
- [ ] Locale works as expected
|
|
296
|
+
|
|
297
|
+
## Additional Resources
|
|
298
|
+
|
|
299
|
+
- **[SSR Example](./SSR-EXAMPLE.md)** - Complete working example with code samples
|
|
300
|
+
- [Angular Universal Guide](https://angular.dev/guide/ssr)
|
|
301
|
+
- [Angular SSR Documentation](https://angular.dev/guide/ssr)
|
|
302
|
+
- [Platform Detection](https://angular.dev/api/common/isPlatformBrowser)
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
|