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

Commit d269d73

Browse files
ThomasBurlesonkara
authored andcommitted
fix(api): restore orig display mode and more... (#143)
fixes #140, fixes #141.
1 parent b7dffaa commit d269d73

File tree

7 files changed

+110
-33
lines changed

7 files changed

+110
-33
lines changed

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

+46-15
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {ObservableMediaService} from '../../media-query/observable-media-service
1717
import {BreakPointsProvider} from '../../media-query/providers/break-points-provider';
1818
import {BreakPointRegistry} from '../../media-query/breakpoints/break-point-registry';
1919

20-
import {customMatchers, expect} from '../../utils/testing/custom-matchers';
20+
import {customMatchers, expect, NgMatchers} from '../../utils/testing/custom-matchers';
2121
import {
2222
makeCreateTestComponent, expectNativeEl, queryFor
2323
} from '../../utils/testing/helpers';
@@ -27,9 +27,22 @@ import {MediaQueriesModule} from '../../media-query/_module';
2727
describe('hide directive', () => {
2828
let fixture: ComponentFixture<any>;
2929
let createTestComponent = makeCreateTestComponent(() => TestHideComponent);
30-
let activateMediaQuery = (alias) => {
30+
let activateMediaQuery: Function = (alias, useOverlaps = false): void => {
3131
let matchMedia: MockMatchMedia = fixture.debugElement.injector.get(MatchMedia);
32-
matchMedia.activate(alias);
32+
matchMedia.activate(alias, useOverlaps);
33+
};
34+
let makeExpectWithActivation = (_fixture_: ComponentFixture<any>, selector: string) => {
35+
fixture = _fixture_;
36+
return (alias?: string): NgMatchers => {
37+
if (alias) {
38+
activateMediaQuery(alias);
39+
}
40+
fixture.detectChanges();
41+
42+
let nodes = queryFor(fixture, selector);
43+
expect(nodes.length).toEqual(1);
44+
return expect(nodes[0].nativeElement);
45+
};
3346
};
3447

3548
beforeEach(() => {
@@ -102,7 +115,7 @@ describe('hide directive', () => {
102115
</button>
103116
`);
104117
expectNativeEl(fixture, {isHidden: true}).toHaveCssStyle({'display': 'none'});
105-
expectNativeEl(fixture, {isHidden: false}).toHaveCssStyle({'display': 'block'});
118+
expectNativeEl(fixture, {isHidden: false}).toHaveCssStyle({'display': 'inline-block'});
106119
});
107120

108121
it('should use "flex" display style when the element also has an fxLayout', () => {
@@ -226,23 +239,41 @@ describe('hide directive', () => {
226239
</div>
227240
</div>
228241
`;
242+
let expectActivation = makeExpectWithActivation(createTestComponent(template), '.hideOnMd');
229243

230-
fixture = createTestComponent(template);
231-
fixture.detectChanges();
232-
233-
let nodes = queryFor(fixture, ".hideOnMd");
234-
expect(nodes.length).toEqual(1);
235-
expect(nodes[0].nativeElement).toHaveCssStyle({'display': 'block'});
244+
expectActivation().toHaveCssStyle({'display': 'block'});
245+
expectActivation('md').toHaveCssStyle({'display': 'none'});
246+
});
236247

237-
activateMediaQuery('md');
238-
fixture.detectChanges();
248+
it('should restore proper display mode when not hiding', () => {
249+
let template = `
250+
<div>
251+
<span fxHide.xs class="hideOnXs">Label</span>
252+
</div>
253+
`;
254+
let expectActivation = makeExpectWithActivation(createTestComponent(template), '.hideOnXs');
239255

240-
nodes = queryFor(fixture, ".hideOnMd");
241-
expect(nodes.length).toEqual(1);
242-
expect(nodes[0].nativeElement).toHaveCssStyle({'display': 'none'});
256+
expectActivation().toHaveCssStyle({'display': 'inline'});
257+
expectActivation('xs').toHaveCssStyle({'display': 'none'});
258+
expectActivation('md').toHaveCssStyle({'display': 'inline'});
243259
});
244260
});
245261

262+
it('should support hide and show', () => {
263+
fixture = createTestComponent(`
264+
<div fxShow fxHide.gt-sm style="display:inline-block;">
265+
This content to be shown ONLY when gt-sm
266+
</div>
267+
`);
268+
expectNativeEl(fixture).toHaveCssStyle({'display': 'inline-block'});
269+
270+
activateMediaQuery('md', true);
271+
expectNativeEl(fixture).toHaveCssStyle({'display': 'none'});
272+
273+
activateMediaQuery('xs', true);
274+
expectNativeEl(fixture).toHaveCssStyle({'display': 'inline-block'});
275+
});
276+
246277
});
247278

248279

src/lib/flexbox/api/hide.ts

+13-8
Original file line numberDiff line numberDiff line change
@@ -101,14 +101,14 @@ export class HideDirective extends BaseFxDirective implements OnInit, OnChanges,
101101
protected renderer: Renderer) {
102102
super(monitor, elRef, renderer);
103103

104-
this._display = this._getDisplayStyle(); // re-invoke override to use `this._layout`
104+
/**
105+
* The Layout can set the display:flex (and incorrectly affect the Hide/Show directives.
106+
* Whenever Layout [on the same element] resets its CSS, then update the Hide/Show CSS
107+
*/
105108
if (_layout) {
106-
/**
107-
* The Layout can set the display:flex (and incorrectly affect the Hide/Show directives.
108-
* Whenever Layout [on the same element] resets its CSS, then update the Hide/Show CSS
109-
*/
110109
this._layoutWatcher = _layout.layout$.subscribe(() => this._updateWithValue());
111110
}
111+
this._display = this._getDisplayStyle(); // re-invoke override to use `this._layout`
112112
}
113113

114114

@@ -122,8 +122,7 @@ export class HideDirective extends BaseFxDirective implements OnInit, OnChanges,
122122
* unless it was already explicitly defined.
123123
*/
124124
protected _getDisplayStyle(): string {
125-
let element: HTMLElement = this._elementRef.nativeElement;
126-
return (element.style as any)['display'] || (this._layout ? "flex" : "block");
125+
return this._layout ? "flex" : super._getDisplayStyle();
127126
}
128127

129128
/**
@@ -140,9 +139,15 @@ export class HideDirective extends BaseFxDirective implements OnInit, OnChanges,
140139
/**
141140
* After the initial onChanges, build an mqActivation object that bridges
142141
* mql change events to onMediaQueryChange handlers
142+
* NOTE: fxHide has special fallback defaults.
143+
* - If the non-responsive fxHide="" is specified we default to hide==true
144+
* - If the non-responsive fxHide is NOT specified, use default hide == false
145+
* This logic supports mixed usages with fxShow; e.g. `<div fxHide fxShow.gt-sm>`
143146
*/
144147
ngOnInit() {
145-
let value = this._getDefaultVal("hide", false);
148+
// If the attribute 'fxHide' is specified we default to hide==true, otherwise do nothing..
149+
let value = (this._queryInput('hide') == "") ? true : this._getDefaultVal("hide", false);
150+
146151
this._listenForMediaQueryChanges('hide', value, (changes: MediaChange) => {
147152
this._updateWithValue(changes.value);
148153
});

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

+19
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,25 @@ describe('show directive', () => {
199199

200200

201201
});
202+
203+
describe('with fxHide features', () => {
204+
205+
it('should support hide and show', () => {
206+
fixture = createTestComponent(`
207+
<div fxHide fxShow.gt-sm>
208+
This content to be shown ONLY when gt-sm
209+
</div>
210+
`);
211+
expectNativeEl(fixture).toHaveCssStyle({'display': 'none'});
212+
213+
activateMediaQuery('md', true);
214+
expectNativeEl(fixture).toHaveCssStyle({'display': 'block'});
215+
216+
activateMediaQuery('xs', true);
217+
expectNativeEl(fixture).toHaveCssStyle({'display': 'none'});
218+
});
219+
});
220+
202221
});
203222

204223

src/lib/flexbox/api/show.ts

+25-2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import {MediaChange} from '../../media-query/media-change';
2525
import {MediaMonitor} from '../../media-query/media-monitor';
2626

2727
import {LayoutDirective} from './layout';
28+
import {HideDirective} from './hide';
2829

2930

3031
const FALSY = ['false', false, 0];
@@ -100,6 +101,7 @@ export class ShowDirective extends BaseFxDirective implements OnInit, OnChanges,
100101
*/
101102
constructor(monitor: MediaMonitor,
102103
@Optional() @Self() private _layout: LayoutDirective,
104+
@Optional() @Self() private _hide: HideDirective,
103105
protected elRef: ElementRef,
104106
protected renderer: Renderer) {
105107

@@ -148,10 +150,16 @@ export class ShowDirective extends BaseFxDirective implements OnInit, OnChanges,
148150
ngOnInit() {
149151
let value = this._getDefaultVal("show", true);
150152

153+
// Build _mqActivation controller
151154
this._listenForMediaQueryChanges('show', value, (changes: MediaChange) => {
152-
this._updateWithValue(changes.value);
155+
if (!this._delegateToHide(changes)) {
156+
this._updateWithValue(changes.value);
157+
}
153158
});
154-
this._updateWithValue();
159+
160+
if (!this._delegateToHide()) {
161+
this._updateWithValue();
162+
}
155163
}
156164

157165
ngOnDestroy() {
@@ -165,6 +173,21 @@ export class ShowDirective extends BaseFxDirective implements OnInit, OnChanges,
165173
// Protected methods
166174
// *********************************************
167175

176+
/**
177+
* If deactiving Show, then delegate action to the Hide directive if it is
178+
* specified on same element.
179+
*/
180+
protected _delegateToHide(changes?: MediaChange) {
181+
if (this._hide) {
182+
let delegate = (changes && !changes.matches) || (!changes && !this.hasKeyValue('show'));
183+
if (delegate) {
184+
this._hide.ngOnChanges({});
185+
return true;
186+
}
187+
}
188+
return false;
189+
}
190+
168191
/** Validate the visibility value and then update the host's inline display style */
169192
private _updateWithValue(value?: string|number|boolean) {
170193
value = value || this._getDefaultVal("show", true);

src/lib/flexbox/responsive/responsive-activation.ts

+3-6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88
import {Subscription} from 'rxjs/Subscription';
99
import 'rxjs/add/operator/map';
10+
import 'rxjs/add/operator/filter';
1011
import {extendObject} from '../../utils/object-extend';
1112

1213
import {MediaChange, MediaQuerySubscriber} from '../../media-query/media-change';
@@ -23,7 +24,7 @@ export interface BreakPointX extends BreakPoint {
2324
export class KeyOptions {
2425
constructor(public baseKey: string,
2526
public defaultValue: string|number|boolean,
26-
public inputKeys: {[key: string]: any}) {
27+
public inputKeys: { [key: string]: any }) {
2728
}
2829
}
2930

@@ -78,7 +79,7 @@ export class ResponsiveActivation {
7879
*/
7980
get activatedInput(): any {
8081
let key = this.activatedInputKey;
81-
return this._hasKeyValue(key) ? this._lookupKeyValue(key) : this._options.defaultValue;
82+
return this.hasKeyValue(key) ? this._lookupKeyValue(key) : this._options.defaultValue;
8283
}
8384

8485
/**
@@ -211,8 +212,4 @@ export class ResponsiveActivation {
211212
return this._options.inputKeys[key];
212213
}
213214

214-
private _hasKeyValue(key) {
215-
let value = this._options.inputKeys[key];
216-
return typeof value !== 'undefined';
217-
}
218215
}

src/lib/media-query/mock/mock-match-media.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,9 @@ export class MockMediaQueryList implements MediaQueryList {
217217
if (this._listeners.indexOf(listener) === -1) {
218218
this._listeners.push(listener);
219219
}
220-
if (this._isActive) { listener(this); }
220+
if (this._isActive) {
221+
listener(this);
222+
}
221223
}
222224

223225
removeListener(listener: MediaQueryListListener) {

src/lib/utils/testing/custom-matchers.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ export const customMatchers: jasmine.CustomMatcherFactories = {
148148
* (Safari, IE, etc) will use prefixed style instead of defaults.
149149
*/
150150
function hasPrefixedStyles(actual, key, value) {
151-
let hasStyle = getDOM().hasStyle(actual, key, value);
151+
let hasStyle = getDOM().hasStyle(actual, key, value.trim());
152152
if (!hasStyle) {
153153
let prefixedStyles = applyCssPrefixes({[key]: value});
154154
Object.keys(prefixedStyles).forEach(prop => {

0 commit comments

Comments
 (0)