Skip to content
This repository was archived by the owner on Jan 6, 2025. It is now read-only.

Commit 6bbfe23

Browse files
Chris3773CaerusKaru
authored andcommitted
fix(server): breakpoints can be used by MediaObserver (#1087)
MediaObserver on the server was not observing the breakpoints at the same lifecycle as the browser. This change moves the active breakpoints check from BEFORE_APP_SERIALIZED to the ServerMatchMedia service.
1 parent 31cb34e commit 6bbfe23

File tree

2 files changed

+36
-30
lines changed

2 files changed

+36
-30
lines changed

src/lib/server/server-match-media.ts

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,20 @@
77
*/
88
import {DOCUMENT} from '@angular/common';
99
import {Inject, Injectable, NgZone, PLATFORM_ID} from '@angular/core';
10-
import {BreakPoint, ɵMatchMedia as MatchMedia} from '@angular/flex-layout/core';
10+
import {
11+
BreakPoint,
12+
ɵMatchMedia as MatchMedia,
13+
BREAKPOINTS,
14+
LAYOUT_CONFIG,
15+
LayoutConfigOptions
16+
} from '@angular/flex-layout/core';
1117

1218
/**
1319
* Special server-only class to simulate a MediaQueryList and
1420
* - supports manual activation to simulate mediaQuery matching
1521
* - manages listeners
1622
*/
1723
export class ServerMediaQueryList implements MediaQueryList {
18-
private _isActive = false;
1924
private _listeners: MediaQueryListListener[] = [];
2025

2126
get matches(): boolean {
@@ -26,7 +31,7 @@ export class ServerMediaQueryList implements MediaQueryList {
2631
return this._mediaQuery;
2732
}
2833

29-
constructor(private _mediaQuery: string) {}
34+
constructor(private _mediaQuery: string, private _isActive = false) {}
3035

3136
/**
3237
* Destroy the current list by deactivating the
@@ -111,10 +116,28 @@ export class ServerMediaQueryList implements MediaQueryList {
111116
*/
112117
@Injectable()
113118
export class ServerMatchMedia extends MatchMedia {
119+
private _activeBreakpoints: BreakPoint[] = [];
120+
114121
constructor(protected _zone: NgZone,
115122
@Inject(PLATFORM_ID) protected _platformId: Object,
116-
@Inject(DOCUMENT) protected _document: any) {
123+
@Inject(DOCUMENT) protected _document: any,
124+
@Inject(BREAKPOINTS) protected breakpoints: BreakPoint[],
125+
@Inject(LAYOUT_CONFIG) protected layoutConfig: LayoutConfigOptions) {
117126
super(_zone, _platformId, _document);
127+
128+
const serverBps = layoutConfig.ssrObserveBreakpoints;
129+
if (serverBps) {
130+
this._activeBreakpoints = serverBps
131+
.reduce((acc: BreakPoint[], serverBp: string) => {
132+
const foundBp = breakpoints.find(bp => serverBp === bp.alias);
133+
if (!foundBp) {
134+
console.warn(`FlexLayoutServerModule: unknown breakpoint alias "${serverBp}"`);
135+
} else {
136+
acc.push(foundBp);
137+
}
138+
return acc;
139+
}, []);
140+
}
118141
}
119142

120143
/** Activate the specified breakpoint if we're on the server, no-op otherwise */
@@ -138,7 +161,9 @@ export class ServerMatchMedia extends MatchMedia {
138161
* supports 0..n listeners for activation/deactivation
139162
*/
140163
protected buildMQL(query: string): ServerMediaQueryList {
141-
return new ServerMediaQueryList(query);
164+
const isActive = this._activeBreakpoints.some(ab => ab.mediaQuery === query);
165+
166+
return new ServerMediaQueryList(query, isActive);
142167
}
143168
}
144169

src/lib/server/server-provider.ts

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@ import {
1515
BreakPoint,
1616
ɵMatchMedia as MatchMedia,
1717
StylesheetMap,
18-
sortAscendingPriority,
19-
LayoutConfigOptions,
20-
LAYOUT_CONFIG,
18+
sortAscendingPriority
2119
} from '@angular/flex-layout/core';
2220

2321
import {ServerMatchMedia} from './server-match-media';
@@ -33,8 +31,7 @@ import {ServerMatchMedia} from './server-match-media';
3331
*/
3432
export function generateStaticFlexLayoutStyles(serverSheet: StylesheetMap,
3533
mediaController: ServerMatchMedia,
36-
breakpoints: BreakPoint[],
37-
layoutConfig: LayoutConfigOptions) {
34+
breakpoints: BreakPoint[]) {
3835
// Store the custom classes in the following map, that way only
3936
// one class gets allocated per HTMLElement, and each class can
4037
// be referenced in the static media queries
@@ -55,20 +52,7 @@ export function generateStaticFlexLayoutStyles(serverSheet: StylesheetMap,
5552
mediaController.deactivateBreakpoint(breakpoints[i]);
5653
});
5754

58-
const serverBps = layoutConfig.ssrObserveBreakpoints;
59-
if (serverBps) {
60-
serverBps
61-
.reduce((acc: BreakPoint[], serverBp: string) => {
62-
const foundBp = breakpoints.find(bp => serverBp === bp.alias);
63-
if (!foundBp) {
64-
console.warn(`FlexLayoutServerModule: unknown breakpoint alias "${serverBp}"`);
65-
} else {
66-
acc.push(foundBp);
67-
}
68-
return acc;
69-
}, [])
70-
.forEach(mediaController.activateBreakpoint);
71-
}
55+
7256

7357
return styleText;
7458
}
@@ -80,14 +64,12 @@ export function generateStaticFlexLayoutStyles(serverSheet: StylesheetMap,
8064
export function FLEX_SSR_SERIALIZER_FACTORY(serverSheet: StylesheetMap,
8165
mediaController: ServerMatchMedia,
8266
_document: Document,
83-
breakpoints: BreakPoint[],
84-
layoutConfig: LayoutConfigOptions) {
67+
breakpoints: BreakPoint[]) {
8568
return () => {
8669
// This is the style tag that gets inserted into the head of the DOM,
8770
// populated with the manual media queries
8871
const styleTag = _document.createElement('style');
89-
const styleText = generateStaticFlexLayoutStyles(serverSheet, mediaController, breakpoints,
90-
layoutConfig);
72+
const styleText = generateStaticFlexLayoutStyles(serverSheet, mediaController, breakpoints);
9173
styleTag.classList.add(`${CLASS_NAME}ssr`);
9274
styleTag.textContent = styleText;
9375
_document.head!.appendChild(styleTag);
@@ -105,8 +87,7 @@ export const SERVER_PROVIDERS = [
10587
StylesheetMap,
10688
MatchMedia,
10789
DOCUMENT,
108-
BREAKPOINTS,
109-
LAYOUT_CONFIG,
90+
BREAKPOINTS
11091
],
11192
multi: true
11293
},

0 commit comments

Comments
 (0)