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

Commit 980d412

Browse files
ThomasBurlesonmmalerba
authored andcommitted
fix(ngClass): add ngClass selector support (#223)
* add missing static `ngClass` and `class` selectors * add tests to demonstrate fallbacks to static selector values Fixes #206.
1 parent ba0d85d commit 980d412

File tree

2 files changed

+42
-8
lines changed

2 files changed

+42
-8
lines changed

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

+24-2
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,22 @@ describe('class directive', () => {
7171
</div>
7272
`);
7373

74+
expectNativeEl(fixture).toHaveCssClass('existing-class');
75+
activateMediaQuery('xs');
76+
expectNativeEl(fixture).not.toHaveCssClass('existing-class');
77+
78+
activateMediaQuery('lg');
79+
expectNativeEl(fixture).toHaveCssClass('existing-class');
80+
expectNativeEl(fixture).not.toHaveCssClass('xs-class');
81+
});
82+
83+
it('should keep existing ngClass selector', () => {
84+
// @see documentation for @angular/core ngClass =http://bit.ly/2mz0LAa
85+
fixture = createTestComponent(`
86+
<div ngClass="existing-class" ngClass.xs="existing-class xs-class">
87+
</div>
88+
`);
89+
7490
expectNativeEl(fixture).toHaveCssClass('existing-class');
7591
activateMediaQuery('xs');
7692
expectNativeEl(fixture).toHaveCssClass('existing-class');
@@ -80,7 +96,7 @@ describe('class directive', () => {
8096
expectNativeEl(fixture).not.toHaveCssClass('xs-class');
8197
});
8298

83-
it('should allow more than one responsive breakpoint on one element', () => {
99+
it('should support more than one responsive breakpoint on one element', () => {
84100
fixture = createTestComponent(`
85101
<div ngClass.xs="xs-class"
86102
ngClass.md="md-class">
@@ -96,7 +112,8 @@ describe('class directive', () => {
96112

97113
it('should work with ngClass object notation', () => {
98114
fixture = createTestComponent(`
99-
<div [ngClass.xs]="{'xs-1': hasXs1, 'xs-2': hasXs2}">
115+
<div [ngClass]="{'xs-1': hasXs1, 'xs-3': hasXs3}"
116+
[ngClass.xs]="{'xs-1': hasXs1, 'xs-2': hasXs2}">
100117
</div>
101118
`);
102119
activateMediaQuery('xs');
@@ -105,6 +122,11 @@ describe('class directive', () => {
105122

106123
expectNativeEl(fixture, {hasXs1: false, hasXs2: true}).toHaveCssClass('xs-2');
107124
expectNativeEl(fixture, {hasXs1: false, hasXs2: true}).not.toHaveCssClass('xs-1');
125+
126+
activateMediaQuery('md');
127+
expectNativeEl(fixture, {hasXs1: true, hasX2: false, hasXs3: true}).toHaveCssClass('xs-3');
128+
expectNativeEl(fixture, {hasXs1: true, hasX2: false, hasXs3: true}).not.toHaveCssClass('xs-2');
129+
expectNativeEl(fixture, {hasXs1: true, hasX2: false, hasXs3: true}).toHaveCssClass('xs-1');
108130
});
109131

110132
it('should work with ngClass array notation', () => {

src/lib/flexbox/api/class.ts

+18-6
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,28 @@ export type NgClassType = string | string[] | Set<string> | {[klass: string]: an
3232
*/
3333
@Directive({
3434
selector: `
35+
[class],
3536
[class.xs], [class.sm], [class.md], [class.lg], [class.xl],
3637
[class.lt-sm], [class.lt-md], [class.lt-lg], [class.lt-xl],
37-
[class.gt-xs], [class.gt-sm], [class.gt-md], [class.gt-lg],
38-
38+
[class.gt-xs], [class.gt-sm], [class.gt-md], [class.gt-lg],
39+
[ngClass],
3940
[ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl],
4041
[ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl],
4142
[ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]
4243
`
4344
})
4445
export class ClassDirective extends NgClass implements OnInit, OnChanges, OnDestroy {
4546

47+
/**
48+
* Intercept ngClass assignments so we cache the default classes
49+
* which are merged with activated styles or used as fallbacks.
50+
*/
51+
@Input('ngClass')
52+
set ngClassBase(val: NgClassType) {
53+
this._base.cacheInput('class', val, true);
54+
this.ngClass = this._base.inputMap['class'];
55+
}
56+
4657
/* tslint:disable */
4758
@Input('ngClass.xs') set ngClassXs(val: NgClassType) { this._base.cacheInput('classXs', val, true); }
4859
@Input('ngClass.sm') set ngClassSm(val: NgClassType) { this._base.cacheInput('classSm', val, true); };
@@ -61,6 +72,7 @@ export class ClassDirective extends NgClass implements OnInit, OnChanges, OnDest
6172
@Input('ngClass.gt-lg') set ngClassGtLg(val: NgClassType) { this._base.cacheInput('classGtLg', val, true); };
6273

6374
/** Deprecated selectors */
75+
@Input('class') set classBase(val: NgClassType) { this._base.cacheInput('class', val, true); }
6476
@Input('class.xs') set classXs(val: NgClassType) { this._base.cacheInput('classXs', val, true); }
6577
@Input('class.sm') set classSm(val: NgClassType) { this._base.cacheInput('classSm', val, true); };
6678
@Input('class.md') set classMd(val: NgClassType) { this._base.cacheInput('classMd', val, true);};
@@ -94,7 +106,7 @@ export class ClassDirective extends NgClass implements OnInit, OnChanges, OnDest
94106
return (`ngClass${it.suffix}` in changes) || (`class${it.suffix}` in changes);
95107
});
96108
if (changed || this._base.mqActivation) {
97-
this._updateStyle();
109+
this._updateClass();
98110
}
99111
}
100112

@@ -104,16 +116,16 @@ export class ClassDirective extends NgClass implements OnInit, OnChanges, OnDest
104116
*/
105117
ngOnInit() {
106118
this._base.listenForMediaQueryChanges('class', '', (changes: MediaChange) => {
107-
this._updateStyle(changes.value);
119+
this._updateClass(changes.value);
108120
});
109-
this._updateStyle();
121+
this._updateClass();
110122
}
111123

112124
ngOnDestroy() {
113125
this._base.ngOnDestroy();
114126
}
115127

116-
protected _updateStyle(value?: NgClassType) {
128+
protected _updateClass(value?: NgClassType) {
117129
let clazz = value || this._base.queryInput("class") || '';
118130
if (this._base.mqActivation) {
119131
clazz = this._base.mqActivation.activatedInput;

0 commit comments

Comments
 (0)