Skip to content

Commit a1ec81a

Browse files
devversionmmalerba
authored andcommitted
fix(slide-toggle): remove side-margin if slide-toggle label is empty (#6881)
* Removes the side-margin of the actual indicator of the slide-toggle if the user label is empty (similar as in #4730) Fixes #6868
1 parent 2239e7d commit a1ec81a

File tree

5 files changed

+85
-4
lines changed

5 files changed

+85
-4
lines changed

src/lib/slide-toggle/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import {NgModule} from '@angular/core';
1010
import {HAMMER_GESTURE_CONFIG} from '@angular/platform-browser';
1111
import {PlatformModule} from '@angular/cdk/platform';
12+
import {ObserversModule} from '@angular/cdk/observers';
1213
import {MdSlideToggle} from './slide-toggle';
1314
import {
1415
FOCUS_ORIGIN_MONITOR_PROVIDER,
@@ -19,7 +20,7 @@ import {
1920

2021

2122
@NgModule({
22-
imports: [MdRippleModule, MdCommonModule, PlatformModule],
23+
imports: [MdRippleModule, MdCommonModule, PlatformModule, ObserversModule],
2324
exports: [MdSlideToggle, MdCommonModule],
2425
declarations: [MdSlideToggle],
2526
providers: [

src/lib/slide-toggle/slide-toggle.html

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<label class="mat-slide-toggle-label" #label>
22

3-
<div class="mat-slide-toggle-bar">
3+
<div class="mat-slide-toggle-bar"
4+
[class.mat-slide-toggle-bar-no-side-margin]="!labelContent.textContent || !labelContent.textContent.trim()">
45

56
<input #input class="mat-slide-toggle-input cdk-visually-hidden" type="checkbox"
67
[id]="inputId"
@@ -32,7 +33,7 @@
3233

3334
</div>
3435

35-
<span class="mat-slide-toggle-content">
36+
<span class="mat-slide-toggle-content" #labelContent (cdkObserveContent)="_onLabelTextChange()">
3637
<ng-content></ng-content>
3738
</span>
3839
</label>

src/lib/slide-toggle/slide-toggle.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ $mat-slide-toggle-bar-track-width: $mat-slide-toggle-bar-width - $mat-slide-togg
7474
}
7575
}
7676

77+
.mat-slide-toggle-bar-no-side-margin {
78+
margin-left: 0;
79+
margin-right: 0;
80+
}
81+
7782
// The thumb container is responsible for the dragging functionality.
7883
// The container includes the visual thumb and the ripple container element.
7984
.mat-slide-toggle-thumb-container {

src/lib/slide-toggle/slide-toggle.spec.ts

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@ describe('MdSlideToggle without forms', () => {
1616
beforeEach(async(() => {
1717
TestBed.configureTestingModule({
1818
imports: [MdSlideToggleModule],
19-
declarations: [SlideToggleBasic, SlideToggleWithTabindexAttr],
19+
declarations: [
20+
SlideToggleBasic,
21+
SlideToggleWithTabindexAttr,
22+
SlideToggleWithoutLabel
23+
],
2024
providers: [
2125
{provide: HAMMER_GESTURE_CONFIG, useFactory: () => gestureConfig = new TestGestureConfig()}
2226
]
@@ -493,6 +497,62 @@ describe('MdSlideToggle without forms', () => {
493497
expect(slideThumbContainer.classList).not.toContain('mat-dragging');
494498
}));
495499
});
500+
501+
describe('without label', () => {
502+
let fixture: ComponentFixture<SlideToggleWithoutLabel>;
503+
let testComponent: SlideToggleWithoutLabel;
504+
let slideToggleElement: HTMLElement;
505+
let slideToggleBarElement: HTMLElement;
506+
507+
beforeEach(() => {
508+
fixture = TestBed.createComponent(SlideToggleWithoutLabel);
509+
510+
const slideToggleDebugEl = fixture.debugElement.query(By.directive(MdSlideToggle));
511+
512+
testComponent = fixture.componentInstance;
513+
slideToggleElement = slideToggleDebugEl.nativeElement;
514+
slideToggleBarElement = slideToggleDebugEl
515+
.query(By.css('.mat-slide-toggle-bar')).nativeElement;
516+
});
517+
518+
it('should remove margin for slide-toggle without a label', () => {
519+
fixture.detectChanges();
520+
521+
expect(slideToggleBarElement.classList)
522+
.toContain('mat-slide-toggle-bar-no-side-margin');
523+
});
524+
525+
it('should not remove margin if initial label is set through binding', async(() => {
526+
testComponent.label = 'Some content';
527+
fixture.detectChanges();
528+
529+
expect(slideToggleBarElement.classList)
530+
.not.toContain('mat-slide-toggle-bar-no-side-margin');
531+
}));
532+
533+
it('should re-add margin if label is added asynchronously', async(() => {
534+
fixture.detectChanges();
535+
536+
expect(slideToggleBarElement.classList)
537+
.toContain('mat-slide-toggle-bar-no-side-margin');
538+
539+
testComponent.label = 'Some content';
540+
fixture.detectChanges();
541+
542+
// Wait for the MutationObserver to detect the content change and for the cdkObserveContent
543+
// to emit the change event to the slide-toggle.
544+
setTimeout(() => {
545+
// The MutationObserver from the cdkObserveContent directive detected the content change
546+
// and notified the slide-toggle component. The slide-toggle then marks the component as
547+
// dirty by calling `markForCheck()`. This needs to be reflected by the component template
548+
// then.
549+
fixture.detectChanges();
550+
551+
expect(slideToggleElement.classList)
552+
.not.toContain('mat-slide-toggle-bar-no-side-margin');
553+
}, 1);
554+
}));
555+
});
496556
});
497557

498558
describe('MdSlideToggle with forms', () => {
@@ -806,3 +866,10 @@ class SlideToggleWithFormControl {
806866
template: `<md-slide-toggle tabindex="5"></md-slide-toggle>`
807867
})
808868
class SlideToggleWithTabindexAttr {}
869+
870+
@Component({
871+
template: `<md-slide-toggle>{{label}}</md-slide-toggle>`
872+
})
873+
class SlideToggleWithoutLabel {
874+
label: string;
875+
}

src/lib/slide-toggle/slide-toggle.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,13 @@ export class MdSlideToggle extends _MdSlideToggleMixinBase implements OnDestroy,
278278
}
279279
}
280280

281+
/** Method being called whenever the label text changes. */
282+
_onLabelTextChange() {
283+
// This method is getting called whenever the label of the slide-toggle changes.
284+
// Since the slide-toggle uses the OnPush strategy we need to notify it about the change
285+
// that has been recognized by the cdkObserveContent directive.
286+
this._changeDetectorRef.markForCheck();
287+
}
281288
}
282289

283290
/**

0 commit comments

Comments
 (0)