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

Commit dafa6dc

Browse files
fix(fxHide,fxShow): fix standalone breakpoint selectors
* Many directive selectors were missing a `,` separator between then xs and gt-xs breakpoints * fxShow, fxHide preserve and restore the element's original display CSS style * added more tests standalone breakpoint selectors, disabled selectors, and deactivated mediaQueries fixes #62, closes ##59.
1 parent 976d3c2 commit dafa6dc

12 files changed

+263
-79
lines changed

src/lib/flexbox/api/base.ts

+28-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
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, Renderer, OnDestroy} from '@angular/core';
8+
import {ElementRef, Renderer, OnDestroy} from '@angular/core';
99
import {applyCssPrefixes} from '../../utils/auto-prefixer';
1010

1111
import {ResponsiveActivation, KeyOptions} from '../responsive/responsive-activation';
@@ -20,6 +20,11 @@ export type StyleDefinition = string|{[property: string]: string|number};
2020

2121
/** Abstract base class for the Layout API styling directives. */
2222
export abstract class BaseFxDirective implements OnDestroy {
23+
/**
24+
* Original dom Elements CSS display style
25+
*/
26+
protected _display;
27+
2328
/**
2429
* MediaQuery Activation Tracker
2530
*/
@@ -36,6 +41,7 @@ export abstract class BaseFxDirective implements OnDestroy {
3641
constructor(private _mediaMonitor: MediaMonitor,
3742
protected _elementRef: ElementRef,
3843
private _renderer: Renderer) {
44+
this._display = this._getDisplayStyle() || "flex";
3945
}
4046

4147
// *********************************************
@@ -65,6 +71,26 @@ export abstract class BaseFxDirective implements OnDestroy {
6571
// Protected Methods
6672
// *********************************************
6773

74+
/**
75+
* Was the directive's default selector used ?
76+
* If not, use the fallback value!
77+
*/
78+
protected _getDefaultVal(key: string, fallbackVal: any): string|boolean {
79+
let val = this._queryInput(key);
80+
let hasDefaultVal = (val !== undefined && val !== null);
81+
return (hasDefaultVal && val !== '') ? val : fallbackVal;
82+
}
83+
84+
/**
85+
* Quick accessor to the current HTMLElement's `display` style
86+
* Note: this allows use to preserve the original style
87+
* and optional restore it when the mediaQueries deactivate
88+
*/
89+
protected _getDisplayStyle(): string {
90+
let element: HTMLElement = this._elementRef.nativeElement;
91+
return (element.style as any)['display'] || "flex";
92+
}
93+
6894
/**
6995
* Applies styles given via string pair or object map to the directive element.
7096
*/
@@ -140,7 +166,7 @@ export abstract class BaseFxDirective implements OnDestroy {
140166
var array = [];
141167

142168
// iterate backwards ensuring that length is an UInt32
143-
for ( var i = obj.length; i--; ) {
169+
for (var i = obj.length; i--;) {
144170
array[i] = obj[i];
145171
}
146172
return array;

src/lib/flexbox/api/flex-align.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import {MediaMonitor} from '../../media-query/media-monitor';
2828
@Directive({
2929
selector: `
3030
[fxFlexAlign],
31-
[fxFlexAlign.xs]
31+
[fxFlexAlign.xs],
3232
[fxFlexAlign.gt-xs],
3333
[fxFlexAlign.sm],
3434
[fxFlexAlign.gt-sm]

src/lib/flexbox/api/flex-offset.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import {MediaMonitor} from '../../media-query/media-monitor';
2828
*/
2929
@Directive({selector: `
3030
[fxFlexOffset],
31-
[fxFlexOffset.xs]
31+
[fxFlexOffset.xs],
3232
[fxFlexOffset.gt-xs],
3333
[fxFlexOffset.sm],
3434
[fxFlexOffset.gt-sm]

src/lib/flexbox/api/flex.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export type FlexBasisAlias = 'grow' | 'initial' | 'auto' | 'none' | 'nogrow' | '
4141
@Directive({
4242
selector: `
4343
[fxFlex],
44-
[fxFlex.xs]
44+
[fxFlex.xs],
4545
[fxFlex.gt-xs],
4646
[fxFlex.sm],
4747
[fxFlex.gt-sm]

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

+62-9
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,25 @@
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 {Component, OnInit, Inject} from '@angular/core';
8+
import {
9+
Component, OnInit, Inject
10+
} from '@angular/core';
911
import {CommonModule} from '@angular/common';
1012
import {ComponentFixture, TestBed} from '@angular/core/testing';
1113

1214
import {MockMatchMedia} from '../../media-query/mock/mock-match-media';
1315
import {MatchMedia, MatchMediaObservable} from '../../media-query/match-media';
1416
import {BreakPointsProvider} from '../../media-query/providers/break-points-provider';
1517
import {BreakPointRegistry} from '../../media-query/breakpoints/break-point-registry';
16-
import {FlexLayoutModule} from '../_module';
1718

1819
import {customMatchers} from '../../utils/testing/custom-matchers';
19-
import {makeCreateTestComponent, expectNativeEl} from '../../utils/testing/helpers';
20+
import {
21+
makeCreateTestComponent, expectNativeEl,
22+
} from '../../utils/testing/helpers';
23+
import {HideDirective} from './hide';
24+
import {MediaQueriesModule} from '../../media-query/_module';
2025

21-
describe('show directive', () => {
26+
describe('hide directive', () => {
2227
let fixture: ComponentFixture<any>;
2328
let createTestComponent = makeCreateTestComponent(() => TestHideComponent);
2429
let activateMediaQuery = (alias) => {
@@ -29,10 +34,11 @@ describe('show directive', () => {
2934
beforeEach(() => {
3035
jasmine.addMatchers(customMatchers);
3136

37+
3238
// Configure testbed to prepare services
3339
TestBed.configureTestingModule({
34-
imports: [CommonModule, FlexLayoutModule.forRoot()],
35-
declarations: [TestHideComponent],
40+
imports: [CommonModule, MediaQueriesModule.forRoot()],
41+
declarations: [TestHideComponent, HideDirective],
3642
providers: [
3743
BreakPointRegistry, BreakPointsProvider,
3844
{provide: MatchMedia, useClass: MockMatchMedia}
@@ -77,7 +83,7 @@ describe('show directive', () => {
7783

7884
it('should update styles with binding changes', () => {
7985
fixture = createTestComponent(`
80-
<div [fxHide]="menuHidden" >
86+
<div [fxHide]="menuHidden">
8187
...content
8288
</div>
8389
`);
@@ -92,7 +98,7 @@ describe('show directive', () => {
9298

9399
describe('with responsive features', () => {
94100

95-
it('should show on `xs` viewports only', () => {
101+
it('should show on `xs` viewports only when the default is included', () => {
96102
fixture = createTestComponent(`
97103
<div fxHide="" fxHide.xs="false" >
98104
...content
@@ -108,6 +114,52 @@ describe('show directive', () => {
108114

109115
});
110116

117+
it('should preserve display and update only on activated mediaQuery', () => {
118+
fixture = createTestComponent(`
119+
<div [fxHide.xs]="isHidden" style="display:inline-block"></div>
120+
`);
121+
expectNativeEl(fixture).toHaveCssStyle({'display': 'inline-block'});
122+
123+
// should hide with this activation
124+
activateMediaQuery('xs');
125+
expectNativeEl(fixture).toHaveCssStyle({'display': 'none'});
126+
127+
// should reset to original display style
128+
activateMediaQuery('md');
129+
expectNativeEl(fixture).toHaveCssStyle({'display': 'inline-block'});
130+
});
131+
132+
it('should restore original display when disabled', () => {
133+
fixture = createTestComponent(`
134+
<div [fxHide.xs]="isHidden" style="display:inline-block"></div>
135+
`);
136+
expectNativeEl(fixture).toHaveCssStyle({'display': 'inline-block'});
137+
138+
// should hide with this activation
139+
activateMediaQuery('xs');
140+
expectNativeEl(fixture).toHaveCssStyle({'display': 'none'});
141+
142+
// should reset to original display style
143+
fixture.componentInstance.isHidden = false;
144+
expectNativeEl(fixture).toHaveCssStyle({'display': 'inline-block'});
145+
});
146+
147+
it('should restore original display when the mediaQuery deactivates', () => {
148+
let originalDisplay = {'display': 'table'};
149+
fixture = createTestComponent(`
150+
<div [fxHide.xs]="isHidden" style="display:table"></div>
151+
`);
152+
expectNativeEl(fixture).toHaveCssStyle(originalDisplay);
153+
154+
// should hide with this activation
155+
activateMediaQuery('xs');
156+
expectNativeEl(fixture).toHaveCssStyle({'display': 'none'});
157+
158+
// should reset to original display style
159+
activateMediaQuery('md');
160+
expectNativeEl(fixture).toHaveCssStyle(originalDisplay);
161+
});
162+
111163
it('should support use of the `media` observable in templates ', () => {
112164
fixture = createTestComponent(`
113165
<div [fxHide]="media.isActive('xs')" >
@@ -150,7 +202,8 @@ describe('show directive', () => {
150202
})
151203
export class TestHideComponent implements OnInit {
152204
isVisible = 0;
153-
menuHidden: boolean = true;
205+
isHidden = true;
206+
menuHidden = true;
154207

155208
constructor(@Inject(MatchMediaObservable) private media) {
156209
}

src/lib/flexbox/api/hide.ts

+55-28
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,10 @@ import {LayoutDirective} from './layout';
3030
* 'show' Layout API directive
3131
*
3232
*/
33-
@Directive({selector: `
33+
@Directive({
34+
selector: `
3435
[fxHide],
35-
[fxHide.xs]
36+
[fxHide.xs],
3637
[fxHide.gt-xs],
3738
[fxHide.sm],
3839
[fxHide.gt-sm]
@@ -41,38 +42,63 @@ import {LayoutDirective} from './layout';
4142
[fxHide.lg],
4243
[fxHide.gt-lg],
4344
[fxHide.xl]
44-
`})
45+
`
46+
})
4547
export class HideDirective extends BaseFxDirective implements OnInit, OnChanges, OnDestroy {
46-
/**
47-
* Original dom Elements CSS display style
48-
*/
49-
private _display = 'flex';
5048

5149
/**
52-
* Subscription to the parent flex container's layout changes.
53-
* Stored so we can unsubscribe when this directive is destroyed.
54-
*/
50+
* Subscription to the parent flex container's layout changes.
51+
* Stored so we can unsubscribe when this directive is destroyed.
52+
*/
5553
private _layoutWatcher: Subscription;
5654

57-
@Input('fxHide') set hide(val) { this._cacheInput("hide", val); }
58-
@Input('fxHide.xs') set hideXs(val) { this._cacheInput('hideXs', val); }
59-
@Input('fxHide.gt-xs') set hideGtXs(val) { this._cacheInput('hideGtXs', val); };
60-
@Input('fxHide.sm') set hideSm(val) { this._cacheInput('hideSm', val); };
61-
@Input('fxHide.gt-sm') set hideGtSm(val) { this._cacheInput('hideGtSm', val); };
62-
@Input('fxHide.md') set hideMd(val) { this._cacheInput('hideMd', val); };
63-
@Input('fxHide.gt-md') set hideGtMd(val) { this._cacheInput('hideGtMd', val); };
64-
@Input('fxHide.lg') set hideLg(val) { this._cacheInput('hideLg', val); };
65-
@Input('fxHide.gt-lg') set hideGtLg(val) { this._cacheInput('hideGtLg', val); };
66-
@Input('fxHide.xl') set hideXl(val) { this._cacheInput('hideXl', val); };
55+
@Input('fxHide') set hide(val) {
56+
this._cacheInput("hide", val);
57+
}
58+
59+
@Input('fxHide.xs') set hideXs(val) {
60+
this._cacheInput('hideXs', val);
61+
}
62+
63+
@Input('fxHide.gt-xs') set hideGtXs(val) {
64+
this._cacheInput('hideGtXs', val);
65+
};
66+
67+
@Input('fxHide.sm') set hideSm(val) {
68+
this._cacheInput('hideSm', val);
69+
};
70+
71+
@Input('fxHide.gt-sm') set hideGtSm(val) {
72+
this._cacheInput('hideGtSm', val);
73+
};
74+
75+
@Input('fxHide.md') set hideMd(val) {
76+
this._cacheInput('hideMd', val);
77+
};
78+
79+
@Input('fxHide.gt-md') set hideGtMd(val) {
80+
this._cacheInput('hideGtMd', val);
81+
};
82+
83+
@Input('fxHide.lg') set hideLg(val) {
84+
this._cacheInput('hideLg', val);
85+
};
86+
87+
@Input('fxHide.gt-lg') set hideGtLg(val) {
88+
this._cacheInput('hideGtLg', val);
89+
};
90+
91+
@Input('fxHide.xl') set hideXl(val) {
92+
this._cacheInput('hideXl', val);
93+
};
6794

6895
/**
6996
*
7097
*/
71-
constructor(
72-
monitor: MediaMonitor,
73-
@Optional() @Self() private _layout: LayoutDirective,
74-
protected elRef: ElementRef,
75-
protected renderer: Renderer) {
98+
constructor(monitor: MediaMonitor,
99+
@Optional() @Self() private _layout: LayoutDirective,
100+
protected elRef: ElementRef,
101+
protected renderer: Renderer) {
76102
super(monitor, elRef, renderer);
77103

78104
if (_layout) {
@@ -105,7 +131,8 @@ export class HideDirective extends BaseFxDirective implements OnInit, OnChanges,
105131
* mql change events to onMediaQueryChange handlers
106132
*/
107133
ngOnInit() {
108-
this._listenForMediaQueryChanges('hide', true, (changes: MediaChange) => {
134+
let value = this._getDefaultVal("hide", false);
135+
this._listenForMediaQueryChanges('hide', value, (changes: MediaChange) => {
109136
this._updateWithValue(changes.value);
110137
});
111138
this._updateWithValue();
@@ -127,7 +154,7 @@ export class HideDirective extends BaseFxDirective implements OnInit, OnChanges,
127154
* Validate the visibility value and then update the host's inline display style
128155
*/
129156
private _updateWithValue(value?: string|number|boolean) {
130-
value = value || this._queryInput("hide") || true;
157+
value = value || this._getDefaultVal("hide", false);
131158
if (this._mqActivation) {
132159
value = this._mqActivation.activatedInput;
133160
}
@@ -141,7 +168,7 @@ export class HideDirective extends BaseFxDirective implements OnInit, OnChanges,
141168
* Build the CSS that should be assigned to the element instance
142169
*/
143170
private _buildCSS(value) {
144-
return {'display': value ? 'none' : this._display };
171+
return {'display': value ? 'none' : this._display};
145172
}
146173

147174
/**

src/lib/flexbox/api/layout-align.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ import {LAYOUT_VALUES, LayoutDirective} from './layout';
3737
*/
3838
@Directive({selector: `
3939
[fxLayoutAlign],
40-
[fxLayoutAlign.xs]
40+
[fxLayoutAlign.xs],
4141
[fxLayoutAlign.gt-xs],
4242
[fxLayoutAlign.sm],
4343
[fxLayoutAlign.gt-sm]

src/lib/flexbox/api/layout-gap.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import {LayoutDirective, LAYOUT_VALUES} from './layout';
3030
*/
3131
@Directive({selector: `
3232
[fxLayoutGap],
33-
[fxLayoutGap.xs]
33+
[fxLayoutGap.xs],
3434
[fxLayoutGap.gt-xs],
3535
[fxLayoutGap.sm],
3636
[fxLayoutGap.gt-sm]

src/lib/flexbox/api/layout-wrap.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import {LayoutDirective, LAYOUT_VALUES} from './layout';
3131
*/
3232
@Directive({selector: `
3333
[fxLayoutWrap],
34-
[fxLayoutWrap.xs]
34+
[fxLayoutWrap.xs],
3535
[fxLayoutWrap.gt-xs],
3636
[fxLayoutWrap.sm],
3737
[fxLayoutWrap.gt-sm]

src/lib/flexbox/api/layout.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export const LAYOUT_VALUES = ['row', 'column', 'row-reverse', 'column-reverse'];
3333
*/
3434
@Directive({selector: `
3535
[fxLayout],
36-
[fxLayout.xs]
36+
[fxLayout.xs],
3737
[fxLayout.gt-xs],
3838
[fxLayout.sm],
3939
[fxLayout.gt-sm]

0 commit comments

Comments
 (0)