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

Commit 305ab8f

Browse files
CaerusKaruThomasBurleson
authored andcommitted
feat(ssr): enhance support for Universal and SSR with stylesheets
* Add StylerService class to manage application and retrieval of styles from elements in a platform-agnostic manner * Add virtual stylesheet to store server styles, which applies default styles when breakpoint overrides are not present * Intercept all style calls and reroute them to the virtual stylesheet while not in the browser * Add a new type of MediaQueryList similar to the MockMediaQueryList for the server that allows for manual activation/deactivation of breakpoints Fixes #373. > See [Design Doc](https://docs.google.com/document/d/1fg04ihw42dJJHGd6fugdiBe39iJot8aErhiE7CjwfmQ/edit#)
1 parent 9214328 commit 305ab8f

33 files changed

+1064
-216
lines changed

src/lib/api/core/base-adapter.spec.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,15 @@
55
* Use of this source code is governed by an MIT-style license that can be
66
* found in the LICENSE file at https://angular.io/license
77
*/
8-
import {ElementRef, Renderer2} from '@angular/core';
8+
import {ElementRef} from '@angular/core';
99
import {BaseFxDirectiveAdapter} from './base-adapter';
1010
import {expect} from '../../utils/testing/custom-matchers';
11-
import {MediaMonitor} from '@angular/flex-layout/media-query';
11+
import {MediaMonitor} from '../../media-query/media-monitor';
12+
<<<<<<< Updated upstream
13+
import {StyleUtils} from '../../utils/style-utils';
14+
=======
15+
import {StylerService} from '../../utils/styling/styler';
16+
>>>>>>> Stashed changes
1217

1318
export class MockElementRef extends ElementRef {
1419
constructor() {
@@ -21,7 +26,11 @@ export class MockElementRef extends ElementRef {
2126
describe('BaseFxDirectiveAdapter class', () => {
2227
let component;
2328
beforeEach(() => {
24-
component = new BaseFxDirectiveAdapter('', {} as MediaMonitor, new MockElementRef(), {} as Renderer2, {}); // tslint:disable-line:max-line-length
29+
<<<<<<< Updated upstream
30+
component = new BaseFxDirectiveAdapter('', {} as MediaMonitor, new MockElementRef(), {} as StyleUtils); // tslint:disable-line:max-line-length
31+
=======
32+
component = new BaseFxDirectiveAdapter('', {} as MediaMonitor, new MockElementRef(), {} as StylerService); // tslint:disable-line:max-line-length
33+
>>>>>>> Stashed changes
2534
});
2635
describe('cacheInput', () => {
2736
it('should call _cacheInputArray when source is an array', () => {

src/lib/api/core/base-adapter.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,17 @@
55
* Use of this source code is governed by an MIT-style license that can be
66
* found in the LICENSE file at https://angular.io/license
77
*/
8-
import {ElementRef, Inject, PLATFORM_ID, Renderer2} from '@angular/core';
8+
import {ElementRef} from '@angular/core';
99

1010
import {BaseFxDirective} from './base';
1111
import {ResponsiveActivation} from './responsive-activation';
1212
import {MediaQuerySubscriber} from '../../media-query/media-change';
1313
import {MediaMonitor} from '../../media-query/media-monitor';
14+
<<<<<<< Updated upstream
15+
import {StyleUtils} from '../../utils/style-utils';
16+
=======
17+
import {StylerService} from '../../utils/styling/styler';
18+
>>>>>>> Stashed changes
1419

1520

1621
/**
@@ -48,9 +53,13 @@ export class BaseFxDirectiveAdapter extends BaseFxDirective {
4853
constructor(protected _baseKey: string, // non-responsive @Input property name
4954
protected _mediaMonitor: MediaMonitor,
5055
protected _elementRef: ElementRef,
51-
protected _renderer: Renderer2,
52-
@Inject(PLATFORM_ID) protected _platformId: Object) {
53-
super(_mediaMonitor, _elementRef, _renderer, _platformId);
56+
<<<<<<< Updated upstream
57+
protected _styleUtils: StyleUtils) {
58+
super(_mediaMonitor, _elementRef, _styleUtils);
59+
=======
60+
protected _styler: StylerService) {
61+
super(_mediaMonitor, _elementRef, _styler);
62+
>>>>>>> Stashed changes
5463
}
5564

5665
/**

src/lib/api/core/base.ts

Lines changed: 53 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,18 @@ import {
1111
SimpleChanges,
1212
OnChanges,
1313
SimpleChange,
14-
Renderer2,
15-
Inject,
16-
PLATFORM_ID,
1714
} from '@angular/core';
1815

1916
import {buildLayoutCSS} from '../../utils/layout-validator';
2017
import {
2118
StyleDefinition,
22-
lookupStyle,
23-
lookupInlineStyle,
24-
applyStyleToElement,
25-
applyStyleToElements,
26-
lookupAttributeValue,
19+
<<<<<<< Updated upstream
20+
StyleUtils,
2721
} from '../../utils/style-utils';
22+
=======
23+
StylerService,
24+
} from '../../utils/styling/styler';
25+
>>>>>>> Stashed changes
2826

2927
import {ResponsiveActivation, KeyOptions} from '../core/responsive-activation';
3028
import {MediaMonitor} from '../../media-query/media-monitor';
@@ -70,8 +68,11 @@ export abstract class BaseFxDirective implements OnDestroy, OnChanges {
7068
*/
7169
constructor(protected _mediaMonitor: MediaMonitor,
7270
protected _elementRef: ElementRef,
73-
protected _renderer: Renderer2,
74-
@Inject(PLATFORM_ID) protected _platformId: Object) {
71+
<<<<<<< Updated upstream
72+
protected _styleUtils: StyleUtils) {
73+
=======
74+
protected _styler: StylerService) {
75+
>>>>>>> Stashed changes
7576
}
7677

7778
// *********************************************
@@ -137,19 +138,28 @@ export abstract class BaseFxDirective implements OnDestroy, OnChanges {
137138

138139
/**
139140
* Quick accessor to the current HTMLElement's `display` style
140-
* Note: this allows use to preserve the original style
141+
* Note: this allows us to preserve the original style
141142
* and optional restore it when the mediaQueries deactivate
142143
*/
143144
protected _getDisplayStyle(source: HTMLElement = this.nativeElement): string {
144-
return lookupStyle(this._platformId, source || this.nativeElement, 'display');
145+
const query = 'display';
146+
<<<<<<< Updated upstream
147+
return this._styleUtils.lookupStyle(source, query);
148+
=======
149+
return this._styler.lookupStyle(source, query);
150+
>>>>>>> Stashed changes
145151
}
146152

147153
/**
148154
* Quick accessor to raw attribute value on the target DOM element
149155
*/
150156
protected _getAttributeValue(attribute: string,
151157
source: HTMLElement = this.nativeElement): string {
152-
return lookupAttributeValue(source || this.nativeElement, attribute);
158+
<<<<<<< Updated upstream
159+
return this._styleUtils.lookupAttributeValue(source, attribute);
160+
=======
161+
return this._styler.lookupAttributeValue(source, attribute);
162+
>>>>>>> Stashed changes
153163
}
154164

155165
/**
@@ -158,15 +168,29 @@ export abstract class BaseFxDirective implements OnDestroy, OnChanges {
158168
* Check inline style first then check computed (stylesheet) style.
159169
* And optionally add the flow value to element's inline style.
160170
*/
161-
protected _getFlowDirection(target: any, addIfMissing = false): string {
171+
protected _getFlowDirection(target: HTMLElement, addIfMissing = false): string {
162172
let value = 'row';
173+
let hasInlineValue = '';
174+
const query = 'flex-direction';
163175

164176
if (target) {
165-
value = lookupStyle(this._platformId, target, 'flex-direction') || 'row';
166-
let hasInlineValue = lookupInlineStyle(target, 'flex-direction');
177+
178+
<<<<<<< Updated upstream
179+
value = this._styleUtils.lookupStyle(target, query) || 'row';
180+
hasInlineValue = this._styleUtils.lookupInlineStyle(target, query);
181+
=======
182+
value = this._styler.lookupStyle(target, query) || 'row';
183+
hasInlineValue = this._styler.lookupInlineStyle(target, query);
184+
>>>>>>> Stashed changes
167185

168186
if (!hasInlineValue && addIfMissing) {
169-
applyStyleToElements(this._renderer, buildLayoutCSS(value), [target]);
187+
const style = buildLayoutCSS(value);
188+
const elements = [target];
189+
<<<<<<< Updated upstream
190+
this._styleUtils.applyStyleToElements(style, elements);
191+
=======
192+
this._styler.applyStyleToElements(style, elements);
193+
>>>>>>> Stashed changes
170194
}
171195
}
172196

@@ -178,16 +202,23 @@ export abstract class BaseFxDirective implements OnDestroy, OnChanges {
178202
*/
179203
protected _applyStyleToElement(style: StyleDefinition,
180204
value?: string | number,
181-
nativeElement: any = this.nativeElement) {
182-
let element = nativeElement || this.nativeElement;
183-
applyStyleToElement(this._renderer, element, style, value);
205+
element: HTMLElement = this.nativeElement) {
206+
<<<<<<< Updated upstream
207+
this._styleUtils.applyStyleToElement(element, style, value);
208+
=======
209+
this._styler.applyStyleToElement(element, style, value);
210+
>>>>>>> Stashed changes
184211
}
185212

186213
/**
187214
* Applies styles given via string pair or object map to the directive's element.
188215
*/
189-
protected _applyStyleToElements(style: StyleDefinition, elements: HTMLElement[ ]) {
190-
applyStyleToElements(this._renderer, style, elements || []);
216+
protected _applyStyleToElements(style: StyleDefinition, elements: HTMLElement[]) {
217+
<<<<<<< Updated upstream
218+
this._styleUtils.applyStyleToElements(style, elements);
219+
=======
220+
this._styler.applyStyleToElements(style, elements);
221+
>>>>>>> Stashed changes
191222
}
192223

193224
/**

src/lib/api/ext/class.spec.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ import {BreakPointRegistry} from '../../media-query/breakpoints/break-point-regi
2121

2222
import {ClassDirective} from './class';
2323
import {MediaQueriesModule} from '../../media-query/_module';
24+
<<<<<<< Updated upstream
25+
import {ServerStylesheet} from '../../utils/server-stylesheet';
26+
import {StyleUtils} from '../../utils/style-utils';
27+
=======
28+
import {ServerStylesheet} from '../../utils/styling/server-stylesheet';
29+
import {StylerService} from '../../utils/styling/styler';
30+
>>>>>>> Stashed changes
2431

2532
describe('class directive', () => {
2633
let fixture: ComponentFixture<any>;
@@ -46,7 +53,13 @@ describe('class directive', () => {
4653
declarations: [TestClassComponent, ClassDirective],
4754
providers: [
4855
BreakPointRegistry, DEFAULT_BREAKPOINTS_PROVIDER,
49-
{provide: MatchMedia, useClass: MockMatchMedia}
56+
{provide: MatchMedia, useClass: MockMatchMedia},
57+
ServerStylesheet,
58+
<<<<<<< Updated upstream
59+
StyleUtils,
60+
=======
61+
StylerService,
62+
>>>>>>> Stashed changes
5063
]
5164
});
5265
});

src/lib/api/ext/class.ts

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ import {
1919
SimpleChanges,
2020
Self,
2121
OnInit,
22-
Inject,
23-
PLATFORM_ID,
2422
} from '@angular/core';
2523
import {NgClass} from '@angular/common';
2624

@@ -29,6 +27,11 @@ import {BaseFxDirectiveAdapter} from '../core/base-adapter';
2927
import {MediaChange} from '../../media-query/media-change';
3028
import {MediaMonitor} from '../../media-query/media-monitor';
3129
import {RendererAdapter} from '../core/renderer-adapter';
30+
<<<<<<< Updated upstream
31+
import {StyleUtils} from '../../utils/style-utils';
32+
=======
33+
import {StylerService} from '../../utils/styling/styler';
34+
>>>>>>> Stashed changes
3235

3336
/** NgClass allowed inputs **/
3437
export type NgClassType = string | string[] | Set<string> | {[klass: string]: any};
@@ -95,8 +98,13 @@ export class ClassDirective extends BaseFxDirective
9598
protected _ngEl: ElementRef,
9699
protected _renderer: Renderer2,
97100
@Optional() @Self() private _ngClassInstance: NgClass,
98-
@Inject(PLATFORM_ID) protected _platformId: Object) {
99-
super(monitor, _ngEl, _renderer, _platformId);
101+
<<<<<<< Updated upstream
102+
protected _styleUtils: StyleUtils) {
103+
super(monitor, _ngEl, _styleUtils);
104+
=======
105+
protected _styler: StylerService) {
106+
super(monitor, _ngEl, _styler);
107+
>>>>>>> Stashed changes
100108
this._configureAdapters();
101109
}
102110

@@ -139,7 +147,14 @@ export class ClassDirective extends BaseFxDirective
139147
*/
140148
protected _configureAdapters() {
141149
this._base = new BaseFxDirectiveAdapter(
142-
'ngClass', this.monitor, this._ngEl, this._renderer, this._platformId
150+
'ngClass',
151+
this.monitor,
152+
this._ngEl,
153+
<<<<<<< Updated upstream
154+
this._styleUtils
155+
=======
156+
this._styler
157+
>>>>>>> Stashed changes
143158
);
144159
if (!this._ngClassInstance) {
145160
// Create an instance NgClass Directive instance only if `ngClass=""` has NOT been defined on

src/lib/api/ext/hide.spec.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ import {
2323
} from '../../utils/testing/helpers';
2424
import {ShowHideDirective} from './show-hide';
2525
import {MediaQueriesModule} from '../../media-query/_module';
26+
<<<<<<< Updated upstream
27+
import {ServerStylesheet} from '../../utils/server-stylesheet';
28+
import {StyleUtils} from '../../utils/style-utils';
29+
=======
30+
import {ServerStylesheet} from '../../utils/styling/server-stylesheet';
31+
import {StylerService} from '../../utils/styling/styler';
32+
>>>>>>> Stashed changes
2633

2734
describe('hide directive', () => {
2835
let fixture: ComponentFixture<any>;
@@ -60,7 +67,13 @@ describe('hide directive', () => {
6067
declarations: [TestHideComponent, ShowHideDirective],
6168
providers: [
6269
BreakPointRegistry, DEFAULT_BREAKPOINTS_PROVIDER,
63-
{provide: MatchMedia, useClass: MockMatchMedia}
70+
{provide: MatchMedia, useClass: MockMatchMedia},
71+
ServerStylesheet,
72+
<<<<<<< Updated upstream
73+
StyleUtils,
74+
=======
75+
StylerService,
76+
>>>>>>> Stashed changes
6477
]
6578
});
6679
});

src/lib/api/ext/img-src.ts

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,15 @@ import {
1212
OnInit,
1313
OnChanges,
1414
Renderer2,
15-
Inject,
16-
PLATFORM_ID,
1715
} from '@angular/core';
1816

1917
import {BaseFxDirective} from '../core/base';
2018
import {MediaMonitor} from '../../media-query/media-monitor';
19+
<<<<<<< Updated upstream
20+
import {StyleUtils} from '../../utils/style-utils';
21+
=======
22+
import {StylerService} from '../../utils/styling/styler';
23+
>>>>>>> Stashed changes
2124

2225
/**
2326
* This directive provides a responsive API for the HTML <img> 'src' attribute
@@ -57,12 +60,17 @@ export class ImgSrcDirective extends BaseFxDirective implements OnInit, OnChange
5760
@Input('src.gt-lg') set srcGtLg(val) { this._cacheInput('srcGtLg', val); }
5861
/* tslint:enable */
5962

60-
constructor(elRef: ElementRef,
61-
renderer: Renderer2,
62-
monitor: MediaMonitor,
63-
@Inject(PLATFORM_ID) platformId: Object) {
64-
super(monitor, elRef, renderer, platformId);
65-
this._cacheInput('src', elRef.nativeElement.getAttribute('src') || '');
63+
constructor(protected _elRef: ElementRef,
64+
protected _renderer: Renderer2,
65+
protected _monitor: MediaMonitor,
66+
<<<<<<< Updated upstream
67+
protected _styleUtils: StyleUtils) {
68+
super(_monitor, _elRef, _styleUtils);
69+
=======
70+
protected _styler: StylerService) {
71+
super(_monitor, _elRef, _styler);
72+
>>>>>>> Stashed changes
73+
this._cacheInput('src', _elRef.nativeElement.getAttribute('src') || '');
6674
}
6775

6876
/**

0 commit comments

Comments
 (0)