From 0824635bef9113b60c536fcbc697cc099d309680 Mon Sep 17 00:00:00 2001 From: Adam Plumer Date: Wed, 13 May 2020 14:24:24 -0500 Subject: [PATCH] fix(show-hide): set explicit display fallback for SSR In the event that a user specifies two breakpoints with conflicting show/hide, e.g. fxHide.lt-lg and fxShow.md, fxShow will not be able to re-enable CSS `display`, since there's no equivalent to nulling out the styles, which is what we do when handling it inline in the browser. This sets the property to `initial` in SSR stylesheets only. This should preserve browser behavior where nulling out the styles still works. NOTE: if you have other classes that set the `display` property of an element, they may get overridden in SSR only. This is unavoidable, since getComputedStyle is not available to use in SSR. Fixes #1250 --- src/lib/extended/show-hide/show-hide.ts | 10 ++++++---- src/lib/extended/show-hide/show.spec.ts | 8 ++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/lib/extended/show-hide/show-hide.ts b/src/lib/extended/show-hide/show-hide.ts index 49fc808b7..19064c69e 100644 --- a/src/lib/extended/show-hide/show-hide.ts +++ b/src/lib/extended/show-hide/show-hide.ts @@ -30,13 +30,14 @@ import {takeUntil} from 'rxjs/operators'; export interface ShowHideParent { display: string; + isServer: boolean; } @Injectable({providedIn: 'root'}) export class ShowHideStyleBuilder extends StyleBuilder { buildStyles(show: string, parent: ShowHideParent) { const shouldShow = show === 'true'; - return {'display': shouldShow ? parent.display : 'none'}; + return {'display': shouldShow ? parent.display || (parent.isServer ? 'initial' : '') : 'none'}; } } @@ -44,7 +45,7 @@ export class ShowHideStyleBuilder extends StyleBuilder { export class ShowHideDirective extends BaseDirective2 implements AfterViewInit, OnChanges { protected DIRECTIVE_KEY = 'show-hide'; - /** Original dom Elements CSS display style */ + /** Original DOM Element CSS display style */ protected display: string = ''; protected hasLayout = false; protected hasFlexChild = false; @@ -146,8 +147,9 @@ export class ShowHideDirective extends BaseDirective2 implements AfterViewInit, if (value === '') { return; } - this.addStyles(value ? 'true' : 'false', {display: this.display}); - if (isPlatformServer(this.platformId) && this.serverModuleLoaded) { + const isServer = isPlatformServer(this.platformId); + this.addStyles(value ? 'true' : 'false', {display: this.display, isServer}); + if (isServer && this.serverModuleLoaded) { this.nativeElement.style.setProperty('display', ''); } this.marshal.triggerUpdate(this.parentElement!, 'layout-gap'); diff --git a/src/lib/extended/show-hide/show.spec.ts b/src/lib/extended/show-hide/show.spec.ts index ddddd3352..20c93fb58 100644 --- a/src/lib/extended/show-hide/show.spec.ts +++ b/src/lib/extended/show-hide/show.spec.ts @@ -299,8 +299,8 @@ describe('show directive', () => { 'display': 'inline' }, styler); } else { - expectEl(queryFor(fixture, elSelector)[0]).not.toHaveStyle({ - 'display': '*' + expectEl(queryFor(fixture, elSelector)[0]).toHaveStyle({ + 'display': 'initial' }, styler); } @@ -318,8 +318,8 @@ describe('show directive', () => { 'display': 'inline' }, styler); } else { - expectEl(queryFor(fixture, elSelector)[0]).not.toHaveStyle({ - 'display': '*' + expectEl(queryFor(fixture, elSelector)[0]).toHaveStyle({ + 'display': 'initial' }, styler); } });