Skip to content

Commit

Permalink
fix(fxShow, fxHide): support fxHide+fxShow usages on same element
Browse files Browse the repository at this point in the history
  • Loading branch information
ThomasBurleson committed Feb 16, 2017
1 parent 0797c85 commit 0e05bdd
Show file tree
Hide file tree
Showing 13 changed files with 355 additions and 51 deletions.
6 changes: 3 additions & 3 deletions src/demo-app/app/demo-app/demo-app.css
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,15 @@ div.coloredContainerX > div, div.colorNested > div > div {
text-align: center;
}

div.coloredContainerX > div:nth-child(1), div.colorNested > div > div:nth-child(1) {
div.coloredContainerX > div:nth-child(1), div.colorNested > div > div:nth-child(1), div.box1 {
background-color: #009688;
}

div.coloredContainerX > div:nth-child(2), div.colorNested > div > div:nth-child(2) {
div.coloredContainerX > div:nth-child(2), div.colorNested > div > div:nth-child(2), div.box2 {
background-color: #3949ab;
}

div.coloredContainerX > div:nth-child(3), div.coloredChildren > div:nth-child(3), div.colorNested > div > div:nth-child(3) {
div.coloredContainerX > div:nth-child(3), div.coloredChildren > div:nth-child(3), div.colorNested > div > div:nth-child(3), div.box3 {
background-color: #9c27b0;
}

Expand Down
7 changes: 5 additions & 2 deletions src/demo-app/app/github-issues/DemosGithubIssues.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import {Component} from '@angular/core';
@Component({
selector: 'demos-github-issues',
template: `
<demo-issue-5345></demo-issue-5345>
<demo-issue-9897></demo-issue-9897>
<demo-issue-181></demo-issue-181>
<!--<demo-issue-5345></demo-issue-5345>-->
<!--<demo-issue-9897></demo-issue-9897>-->
`
})
export class DemosGithubIssues { }
Expand All @@ -16,12 +17,14 @@ import {FlexLayoutModule} from "../../../lib"; // `gulp build:components`

import { DemoIssue5345 } from "./issue.5345.demo";
import { DemoIssue9897 } from "./issue.9897.demo";
import {DemoIssue181} from './issue.181.demo';

@NgModule({
declarations : [
DemosGithubIssues, // used by the Router with the root app component
DemoIssue5345,
DemoIssue9897
DemoIssue181
],
imports : [
CommonModule,
Expand Down
60 changes: 60 additions & 0 deletions src/demo-app/app/github-issues/issue.181.demo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import {Component, OnDestroy} from '@angular/core';
import {Subscription} from "rxjs/Subscription";
import 'rxjs/add/operator/filter';

import {MediaChange} from "../../../lib/media-query/media-change";
import {ObservableMedia} from "../../../lib/media-query/observable-media-service";

@Component({
selector: 'demo-issue-181',
styleUrls: [
'../demo-app/material2.css'
],
styles : [
".fixed { height:275px; }"
],
template: `
<md-card class="card-demo" >
<md-card-title><a href="https://github.com/angular/flex-layout/issues/181" target="_blank">Issue #135</a></md-card-title>
<md-card-subtitle>Wrong layout with fxHide / fxShow sometimes ignoring breakpoint aliases:</md-card-subtitle>
<md-card-content>
<div class="containerX">
<div class="coloredContainerX box fixed"
[fxLayout]="direction"
(click)="pivot()">
<div fxHide fxShow.gt-xs class="box1"> Type 1, row a, fxHide fxShow.gt-xs </div>
<div fxHide fxShow.gt-xs class="box2"> Type 1, row b, fxHide fxShow.gt-xs </div>
<div fxHide fxShow.gt-xs class="box3"> Type 1, row c, fxHide fxShow.gt-xs </div>
<div fxShow fxHide.md class="box1"> Type 2, row a, fxShow fxHide.md</div>
<div fxShow fxHide.md class="box2"> Type 2, row b, fxShow fxHide.md</div>
<div fxShow fxHide.md class="box3"> Type 2, row c, fxShow fxHide.md</div>
</div>
</div>
</md-card-content>
<md-card-footer style="width:95%">
<div class="hint" >Active mediaQuery: <span style="padding-left: 20px; color: rgba(0, 0, 0, 0.54)">{{ activeMediaQuery }}</span></div>
</md-card-footer>
</md-card>
`
})
export class DemoIssue181 implements OnDestroy {
public direction = "column";
public activeMediaQuery = "";

constructor(media$: ObservableMedia) {
this._watcher = media$.subscribe((change: MediaChange) => {
let value = change ? `'${change.mqAlias}' = (${change.mediaQuery})` : "";
this.activeMediaQuery = value;
});
}

pivot() {
this.direction = (this.direction === "row") ? "column" : "row";
}
ngOnDestroy() {
this._watcher.unsubscribe();
}

private _watcher: Subscription;
}
11 changes: 7 additions & 4 deletions src/lib/flexbox/_module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/map';

import {ModuleWithProviders, NgModule} from '@angular/core';
import '../utils/rxjs-operators';

import {MediaMonitor} from '../media-query/media-monitor';
import {MediaQueriesModule} from '../media-query/_module';
import {ShowHideConnectorProvider} from './utils/show-hide-connector';

import {FlexDirective} from './api/flex';
import {LayoutDirective} from './api/layout';
Expand Down Expand Up @@ -57,7 +57,10 @@ const ALL_DIRECTIVES = [
declarations: ALL_DIRECTIVES,
imports: [MediaQueriesModule],
exports: [MediaQueriesModule, ...ALL_DIRECTIVES],
providers: [MediaMonitor]
providers: [
MediaMonitor,
ShowHideConnectorProvider
]
})
export class FlexLayoutModule {
/** @deprecated */
Expand Down
10 changes: 7 additions & 3 deletions src/lib/flexbox/api/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,14 @@ import {MediaQuerySubscriber} from '../../media-query/media-change';
* Definition of a css style. Either a property name (e.g. "flex-basis") or an object
* map of property name and value (e.g. {display: 'none', flex-order: 5}).
*/
export type StyleDefinition = string|{ [property: string]: string|number };
export type StyleDefinition = string|{[property: string]: string|number};

/** Abstract base class for the Layout API styling directives. */
export abstract class BaseFxDirective implements OnDestroy {

protected get nativeElement():any {
return this._elementRef ? this._elementRef.nativeElement : null;
}
/**
* Original dom Elements CSS display style
*/
Expand Down Expand Up @@ -171,7 +175,7 @@ export abstract class BaseFxDirective implements OnDestroy {
var buffer = [];

// iterate backwards ensuring that length is an UInt32
for ( var i = obj.length; i--; ) {
for (var i = obj.length; i--;) {
buffer[i] = obj[i];
}
return buffer;
Expand All @@ -181,7 +185,7 @@ export abstract class BaseFxDirective implements OnDestroy {
* Fast validator for presence of attribute on the host element
*/
protected hasKeyValue(key) {
return this._mqActivation.hasKeyValue(key);
return this._mqActivation && this._mqActivation.hasKeyValue(key);
}

}
86 changes: 75 additions & 11 deletions src/lib/flexbox/api/hide.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,19 @@ import {
Renderer,
SimpleChanges,
Self,
Optional
Optional, Inject
} from '@angular/core';

import {Subscription} from 'rxjs/Subscription';
import 'rxjs/add/operator/filter';

import {BaseFxDirective} from './base';
import {MediaChange} from '../../media-query/media-change';
import {MediaMonitor} from '../../media-query/media-monitor';

import {EventBusService, EventBusFilter} from '../../utils/event-bus-service';
import {ShowHideConnector, ConnectorEvents} from '../utils/show-hide-connector';

import {LayoutDirective} from './layout';

/**
Expand Down Expand Up @@ -52,6 +56,8 @@ export class HideDirective extends BaseFxDirective implements OnInit, OnChanges,
*/
protected _layoutWatcher: Subscription;

protected _connectorWatcher: Subscription;

@Input('fxHide') set hide(val) {
this._cacheInput("hide", val);
}
Expand Down Expand Up @@ -96,9 +102,11 @@ export class HideDirective extends BaseFxDirective implements OnInit, OnChanges,
*
*/
constructor(monitor: MediaMonitor,
@Optional() @Self() protected _layout: LayoutDirective,
protected elRef: ElementRef,
protected renderer: Renderer) {
elRef: ElementRef,
renderer: Renderer,
@Inject(ShowHideConnector) protected _connector: EventBusService,
@Optional() @Self() protected _layout: LayoutDirective) {

super(monitor, elRef, renderer);

/**
Expand All @@ -109,6 +117,7 @@ export class HideDirective extends BaseFxDirective implements OnInit, OnChanges,
this._layoutWatcher = _layout.layout$.subscribe(() => this._updateWithValue());
}
this._display = this._getDisplayStyle(); // re-invoke override to use `this._layout`

}


Expand Down Expand Up @@ -137,21 +146,20 @@ export class HideDirective extends BaseFxDirective implements OnInit, OnChanges,
}

/**
* After the initial onChanges, build an mqActivation object that bridges
* After the initial onChanges, build a mqActivation object that bridges
* mql change events to onMediaQueryChange handlers
* NOTE: fxHide has special fallback defaults.
* - If the non-responsive fxHide="" is specified we default to hide==true
* - If the non-responsive fxHide is NOT specified, use default hide == false
* This logic supports mixed usages with fxShow; e.g. `<div fxHide fxShow.gt-sm>`
*/
ngOnInit() {
// If the attribute 'fxHide' is specified we default to hide==true, otherwise do nothing..
let value = (this._queryInput('hide') == "") ? true : this._getDefaultVal("hide", false);
this._activateReponsive();
this._activateConnector();

this._listenForMediaQueryChanges('hide', value, (changes: MediaChange) => {
this._updateWithValue(changes.value);
});
this._updateWithValue();
if (!this._delegateToHide()) {
this._updateWithValue();
}
}


Expand All @@ -160,12 +168,63 @@ export class HideDirective extends BaseFxDirective implements OnInit, OnChanges,
if (this._layoutWatcher) {
this._layoutWatcher.unsubscribe();
}
if (this._connectorWatcher) {
this._connectorWatcher.unsubscribe();
}
}

// *********************************************
// Protected methods
// *********************************************

/**
* Activate the Responsive features using MediaMonitor
* and delegating via the ShowHideConnector if needed.
*/
protected _activateReponsive() {
// If the attribute 'fxHide' is specified we default to hide==true, otherwise do nothing..
let value = (this._queryInput('hide') == "") ? true : this._getDefaultVal("hide", false);

/**
* Listen for responsive changes
*/
this._listenForMediaQueryChanges('hide', value, (changes: MediaChange) => {
this._updateWithValue(changes.value);
});
}

/**
* Use special ShowHideConnector message-bus to listen
* for incoming updateWithHide messages and trigger
* `updateWithValue()`.
*
* NOTE: ShowHideConnector supports messaging ONLY for
* directives on the same element.
*/
protected _activateConnector() {
let isSameElement: EventBusFilter = ((el: any) => (el === this.nativeElement));
this._connectorWatcher = this._connector
.observe(ConnectorEvents.announceHasShow)
.filter(isSameElement)
.subscribe(() => {
this._hasShow = true;
console.log('ConnectorEvents.announceHasShow');
this._connectorWatcher.unsubscribe();
});
// console.log('hide:: ' + this.nativeElement);
this._connector.emit(ConnectorEvents.announceHasHide, this.nativeElement);

}

/**
* If deactivating Show, then delegate action to the Hide directive if it is
* specified on same element.
*/
protected _delegateToHide(changes?: MediaChange) {
let delegate = (!changes || !this.hasKeyValue('hide'));
return delegate && this._hasShow;
}

/**
* Validate the visibility value and then update the host's inline display style
*/
Expand Down Expand Up @@ -193,6 +252,11 @@ export class HideDirective extends BaseFxDirective implements OnInit, OnChanges,
protected _validateTruthy(value) {
return FALSY.indexOf(value) === -1;
}

/**
* Does this element also have fxShow directives?
*/
private _hasShow = false;
}


Expand Down
Loading

0 comments on commit 0e05bdd

Please sign in to comment.