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

Commit 71b2007

Browse files
fix(ngStyle, ngClass): StyleDirective should merge styles instead of overwriting all existing
* Deprecated use of `style` selectors to favor `ngStyle` selectors since the functionality extends NgStyle directive. * Restore default (non-activated) inline styles when breakpoint deactivates * Merge default inline styles with activated styles * `ngStyle` selectors support Object notations or raw strings (ala html inline styles) * e.g. Object notation = `[ngStyle="{'font-size.px': 10, color: 'rgb(0,0,0)', 'text-align':'left'}"` * e.g. Raw-string notation = `style="font-size:10px; color:black; text-align:left;"` BREAKING CHANGE: * `[style.<alias>]` selectors are deprecated in favor of `[ngStyle.<alias>]` selectors * `[class.<alias>]` selectors are deprecated in favor of `[ngClass.<alias>]` selectors * default styles are merged with activated styles ```html <div fxLayout [class.xs]="['xs-1', 'xs-2']" [style]="{'font-size': '10px', 'margin-left' : '13px'}" [style.xs]="{'font-size': '16px'}" [style.md]="{'font-size': '12px'}"> </div> ``` ```html <div fxLayout [ngClass.xs]="['xs-1', 'xs-2']" [ngStyle]="{'font-size': '10px', 'margin-left' : '13px'}" [ngStyle.xs]="{'font-size': '16px'}" [ngStyle.md]="{'font-size': '12px'}"> </div> ``` Fixes #197.
1 parent d95cb09 commit 71b2007

File tree

6 files changed

+298
-192
lines changed

6 files changed

+298
-192
lines changed

src/demo-app/app/github-issues/DemosGithubIssues.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ import {Component} from '@angular/core';
55
template: `
66
<demo-issue-5345></demo-issue-5345>
77
<demo-issue-9897></demo-issue-9897>
8-
<demo-issue-181></demo-issue-181>
98
<demo-issue-135> </demo-issue-135>
9+
<demo-issue-181></demo-issue-181>
10+
<demo-issue-197></demo-issue-197>
1011
`
1112
})
1213
export class DemosGithubIssues {
@@ -19,16 +20,18 @@ import {FlexLayoutModule} from "../../../lib"; // `gulp build:components` to
1920

2021
import {DemoIssue5345} from "./issue.5345.demo";
2122
import {DemoIssue9897} from "./issue.9897.demo";
22-
import {DemoIssue181} from './issue.181.demo';
2323
import {DemoIssue135} from "./issue.135.demo";
24+
import {DemoIssue181} from './issue.181.demo';
25+
import {DemoIssue197} from './issue.197.demo';
2426

2527
@NgModule({
2628
declarations: [
2729
DemosGithubIssues, // used by the Router with the root app component
2830
DemoIssue5345,
2931
DemoIssue9897,
32+
DemoIssue135,
3033
DemoIssue181,
31-
DemoIssue135
34+
DemoIssue197
3235
],
3336
imports: [
3437
CommonModule,
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import {Component, OnDestroy} from '@angular/core';
2+
import {Subscription} from "rxjs/Subscription";
3+
import 'rxjs/add/operator/filter';
4+
5+
import {MediaChange} from "../../../lib/media-query/media-change";
6+
import {ObservableMedia} from "../../../lib/media-query/observable-media-service";
7+
8+
// [ngStyle="{'font-size.px': 10, color: 'rgb(0,0,0)', 'text-align':'left'}"
9+
// style="font-size:10px; color:black; text-align:left;"
10+
@Component({
11+
selector: 'demo-issue-197',
12+
styleUrls: [
13+
'../demo-app/material2.css'
14+
],
15+
template: `
16+
17+
<md-card class="card-demo" >
18+
<md-card-title><a href="https://github.com/angular/flex-layout/issues/197" target="_blank">Issue #197</a></md-card-title>
19+
<md-card-subtitle>Responsive Style directive should merge with default inline style:</md-card-subtitle>
20+
<md-card-content>
21+
<div class="containerX">
22+
<div class="coloredContainerX box fixed">
23+
<div class="box1"
24+
fxFlexFill
25+
style="font-size:10px; color:black; text-align:left;"
26+
[style.md]="{'font-size': '16px', color: 'red'}"
27+
ngStyle.lg="font-size: 24px; color : #00f;">
28+
&lt;div fxFlexFill <br/>
29+
&nbsp;&nbsp;&nbsp;&nbsp;style="font-size:10px; color:black; text-align:left;"<br/>
30+
&nbsp;&nbsp;&nbsp;&nbsp;[style.md]="&#123;'font-size': '16px', color: 'red'&#125;"<br/>
31+
&nbsp;&nbsp;&nbsp;&nbsp;ngStyle.lg="font-size: 24px; color : #00f;" &gt;<br/>
32+
&lt;/div&gt;
33+
</div>
34+
</div>
35+
</div>
36+
</md-card-content>
37+
<md-card-footer style="width:95%;padding-left:20px;margin-top:-5px;">
38+
<div class="hint" >Active mediaQuery: <span style="padding-left: 20px; color: rgba(0, 0, 0, 0.54)">{{ activeMediaQuery }}</span></div>
39+
</md-card-footer>
40+
</md-card>
41+
`
42+
})
43+
export class DemoIssue197 implements OnDestroy {
44+
public activeMediaQuery = "";
45+
46+
constructor(media$: ObservableMedia) {
47+
this._watcher = media$.subscribe((change: MediaChange) => {
48+
let value = change ? `'${change.mqAlias}' = (${change.mediaQuery})` : "";
49+
this.activeMediaQuery = value;
50+
});
51+
}
52+
53+
ngOnDestroy() {
54+
this._watcher.unsubscribe();
55+
}
56+
57+
private _watcher: Subscription;
58+
}

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

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ describe('class directive', () => {
5757
const selector = `class-${mq}`;
5858
it(`should apply '${selector}' with '${mq}' media query`, () => {
5959
fixture = createTestComponent(`
60-
<div class.${mq}="${selector}">
60+
<div ngClass.${mq}="${selector}">
6161
</div>
6262
`);
6363
activateMediaQuery(mq, true);
@@ -67,7 +67,7 @@ describe('class directive', () => {
6767

6868
it('should keep existing class selector', () => {
6969
fixture = createTestComponent(`
70-
<div class="existing-class" class.xs="xs-class">
70+
<div class="existing-class" ngClass.xs="xs-class">
7171
</div>
7272
`);
7373
expectNativeEl(fixture).toHaveCssClass('existing-class');
@@ -77,8 +77,8 @@ describe('class directive', () => {
7777

7878
it('should allow more than one responsive breakpoint on one element', () => {
7979
fixture = createTestComponent(`
80-
<div class.xs="xs-class"
81-
class.md="md-class">
80+
<div ngClass.xs="xs-class"
81+
ngClass.md="md-class">
8282
</div>
8383
`);
8484
activateMediaQuery('xs', true);
@@ -91,9 +91,9 @@ describe('class directive', () => {
9191

9292
it('should work with ngClass object notation', () => {
9393
fixture = createTestComponent(`
94-
<div [class.xs]="{'xs-1': hasXs1, 'xs-2': hasXs2}">
95-
</div>
96-
`);
94+
<div [ngClass.xs]="{'xs-1': hasXs1, 'xs-2': hasXs2}">
95+
</div>
96+
`);
9797
activateMediaQuery('xs', true);
9898
expectNativeEl(fixture, {hasXs1: true, hasXs2: false}).toHaveCssClass('xs-1');
9999
expectNativeEl(fixture, {hasXs1: true, hasXs2: false}).not.toHaveCssClass('xs-2');
@@ -104,9 +104,9 @@ describe('class directive', () => {
104104

105105
it('should work with ngClass array notation', () => {
106106
fixture = createTestComponent(`
107-
<div [class.xs]="['xs-1', 'xs-2']">
108-
</div>
109-
`);
107+
<div [ngClass.xs]="['xs-1', 'xs-2']">
108+
</div>
109+
`);
110110
activateMediaQuery('xs', true);
111111
expectNativeEl(fixture).toHaveCssClass('xs-1');
112112
expectNativeEl(fixture).toHaveCssClass('xs-2');

src/lib/flexbox/api/class.ts

Lines changed: 34 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -32,64 +32,41 @@ export type NgClassType = string | string[] | Set<string> | {[klass: string]: an
3232
*/
3333
@Directive({
3434
selector: `
35-
[class.xs],
36-
[class.gt-xs],
37-
[class.sm],
38-
[class.gt-sm],
39-
[class.md],
40-
[class.gt-md],
41-
[class.lg],
42-
[class.gt-lg],
43-
[class.xl]
35+
[ngClass.xs], [class.xs],
36+
[ngClass.gt-xs], [class.gt-xs],
37+
[ngClass.sm], [class.sm],
38+
[ngClass.gt-sm], [class.gt-sm],
39+
[ngClass.md], [class.md],
40+
[ngClass.gt-md], [class.gt-md],
41+
[ngClass.lg], [class.lg],
42+
[ngClass.gt-lg], [class.gt-lg]
4443
`
4544
})
4645
export class ClassDirective extends NgClass implements OnInit, OnChanges, OnDestroy {
4746

48-
@Input('class.xs')
49-
set classXs(val: NgClassType) {
50-
this._base.cacheInput('classXs', val);
51-
}
52-
53-
@Input('class.gt-xs')
54-
set classGtXs(val: NgClassType) {
55-
this._base.cacheInput('classGtXs', val);
56-
};
57-
58-
@Input('class.sm')
59-
set classSm(val: NgClassType) {
60-
this._base.cacheInput('classSm', val);
61-
};
62-
63-
@Input('class.gt-sm')
64-
set classGtSm(val: NgClassType) {
65-
this._base.cacheInput('classGtSm', val);
66-
};
67-
68-
@Input('class.md')
69-
set classMd(val: NgClassType) {
70-
this._base.cacheInput('classMd', val);
71-
};
72-
73-
@Input('class.gt-md')
74-
set classGtMd(val: NgClassType) {
75-
this._base.cacheInput('classGtMd', val);
76-
};
77-
78-
@Input('class.lg')
79-
set classLg(val: NgClassType) {
80-
this._base.cacheInput('classLg', val);
81-
};
82-
83-
@Input('class.gt-lg')
84-
set classGtLg(val: NgClassType) {
85-
this._base.cacheInput('classGtLg', val);
86-
};
87-
88-
@Input('class.xl')
89-
set classXl(val: NgClassType) {
90-
this._base.cacheInput('classXl', val);
91-
};
92-
47+
/* tslint:disable */
48+
@Input('ngClass.xs') set ngClassXs(val: NgClassType) { this._base.cacheInput('classXs', val, true); }
49+
@Input('ngClass.gt-xs') set ngClassGtXs(val: NgClassType) { this._base.cacheInput('classGtXs', val, true); };
50+
@Input('ngClass.sm') set ngClassSm(val: NgClassType) { this._base.cacheInput('classSm', val, true); };
51+
@Input('ngClass.gt-sm') set ngClassGtSm(val: NgClassType) { this._base.cacheInput('classGtSm', val, true);} ;
52+
@Input('ngClass.md') set ngClassMd(val: NgClassType) { this._base.cacheInput('classMd', val, true); };
53+
@Input('ngClass.gt-md') set ngClassGtMd(val: NgClassType) { this._base.cacheInput('classGtMd', val, true);};
54+
@Input('ngClass.lg') set ngClassLg(val: NgClassType) { this._base.cacheInput('classLg', val, true);};
55+
@Input('ngClass.gt-lg') set ngClassGtLg(val: NgClassType) { this._base.cacheInput('classGtLg', val, true); };
56+
@Input('ngClass.xl') set ngClassXl(val: NgClassType) { this._base.cacheInput('classXl', val, true); };
57+
58+
/** Deprecated selectors */
59+
@Input('class.xs') set classXs(val: NgClassType) { this._base.cacheInput('classXs', val, true); }
60+
@Input('class.gt-xs') set classGtXs(val: NgClassType) { this._base.cacheInput('classGtXs', val, true); };
61+
@Input('class.sm') set classSm(val: NgClassType) { this._base.cacheInput('classSm', val, true); };
62+
@Input('class.gt-sm') set classGtSm(val: NgClassType) { this._base.cacheInput('classGtSm', val, true); };
63+
@Input('class.md') set classMd(val: NgClassType) { this._base.cacheInput('classMd', val, true);};
64+
@Input('class.gt-md') set classGtMd(val: NgClassType) { this._base.cacheInput('classGtMd', val, true);};
65+
@Input('class.lg') set classLg(val: NgClassType) { this._base.cacheInput('classLg', val, true); };
66+
@Input('class.gt-lg') set classGtLg(val: NgClassType) { this._base.cacheInput('classGtLg', val, true); };
67+
@Input('class.xl') set classXl(val: NgClassType) { this._base.cacheInput('classXl', val, true); };
68+
69+
/* tslint:enable */
9370
constructor(private monitor: MediaMonitor,
9471
private _bpRegistry: BreakPointRegistry,
9572
_iterableDiffers: IterableDiffers, _keyValueDiffers: KeyValueDiffers,
@@ -102,7 +79,9 @@ export class ClassDirective extends NgClass implements OnInit, OnChanges, OnDest
10279
* For @Input changes on the current mq activation property, see onMediaQueryChanges()
10380
*/
10481
ngOnChanges(changes: SimpleChanges) {
105-
const changed = this._bpRegistry.items.some(it => `class${it.suffix}` in changes);
82+
const changed = this._bpRegistry.items.some(it => {
83+
return (`ngClass${it.suffix}` in changes) || (`class${it.suffix}` in changes);
84+
});
10685
if (changed || this._base.mqActivation) {
10786
this._updateStyle();
10887
}

0 commit comments

Comments
 (0)