Skip to content

Commit

Permalink
fix(slide-toggle): remove side-margin if slide-toggle label is empty
Browse files Browse the repository at this point in the history
* Removes the side-margin of the actual indicator of the slide-toggle if the user label is empty (similar as in #4730)

Fixes #6868
  • Loading branch information
devversion committed Sep 7, 2017
1 parent 1b6b270 commit c476c0a
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 4 deletions.
3 changes: 2 additions & 1 deletion src/lib/slide-toggle/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import {NgModule} from '@angular/core';
import {HAMMER_GESTURE_CONFIG} from '@angular/platform-browser';
import {PlatformModule} from '@angular/cdk/platform';
import {ObserversModule} from '@angular/cdk/observers';
import {MdSlideToggle} from './slide-toggle';
import {
FOCUS_ORIGIN_MONITOR_PROVIDER,
Expand All @@ -19,7 +20,7 @@ import {


@NgModule({
imports: [MdRippleModule, MdCommonModule, PlatformModule],
imports: [MdRippleModule, MdCommonModule, PlatformModule, ObserversModule],
exports: [MdSlideToggle, MdCommonModule],
declarations: [MdSlideToggle],
providers: [
Expand Down
5 changes: 3 additions & 2 deletions src/lib/slide-toggle/slide-toggle.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<label class="mat-slide-toggle-label" #label>

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

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

</div>

<span class="mat-slide-toggle-content">
<span class="mat-slide-toggle-content" #labelContent (cdkObserveContent)="_onLabelTextChange()">
<ng-content></ng-content>
</span>
</label>
5 changes: 5 additions & 0 deletions src/lib/slide-toggle/slide-toggle.scss
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ $mat-slide-toggle-bar-track-width: $mat-slide-toggle-bar-width - $mat-slide-togg
}
}

.mat-slide-toggle-bar-no-side-margin {
margin-left: 0;
margin-right: 0;
}

// The thumb container is responsible for the dragging functionality.
// The container includes the visual thumb and the ripple container element.
.mat-slide-toggle-thumb-container {
Expand Down
69 changes: 68 additions & 1 deletion src/lib/slide-toggle/slide-toggle.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ describe('MdSlideToggle without forms', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [MdSlideToggleModule],
declarations: [SlideToggleBasic, SlideToggleWithTabindexAttr],
declarations: [
SlideToggleBasic,
SlideToggleWithTabindexAttr,
SlideToggleWithoutLabel
],
providers: [
{provide: HAMMER_GESTURE_CONFIG, useFactory: () => gestureConfig = new TestGestureConfig()}
]
Expand Down Expand Up @@ -493,6 +497,62 @@ describe('MdSlideToggle without forms', () => {
expect(slideThumbContainer.classList).not.toContain('mat-dragging');
}));
});

describe('without label', () => {
let fixture: ComponentFixture<SlideToggleWithoutLabel>;
let testComponent: SlideToggleWithoutLabel;
let slideToggleElement: HTMLElement;
let slideToggleBarElement: HTMLElement;

beforeEach(() => {
fixture = TestBed.createComponent(SlideToggleWithoutLabel);

const slideToggleDebugEl = fixture.debugElement.query(By.directive(MdSlideToggle));

testComponent = fixture.componentInstance;
slideToggleElement = slideToggleDebugEl.nativeElement;
slideToggleBarElement = slideToggleDebugEl
.query(By.css('.mat-slide-toggle-bar')).nativeElement;
});

it('should remove margin for slide-toggle without a label', () => {
fixture.detectChanges();

expect(slideToggleBarElement.classList)
.toContain('mat-slide-toggle-bar-no-side-margin');
});

it('should not remove margin if initial label is set through binding', async(() => {
testComponent.label = 'Some content';
fixture.detectChanges();

expect(slideToggleBarElement.classList)
.not.toContain('mat-slide-toggle-bar-no-side-margin');
}));

it('should re-add margin if label is added asynchronously', async(() => {
fixture.detectChanges();

expect(slideToggleBarElement.classList)
.toContain('mat-slide-toggle-bar-no-side-margin');

testComponent.label = 'Some content';
fixture.detectChanges();

// Wait for the MutationObserver to detect the content change and for the cdkObserveContent
// to emit the change event to the slide-toggle.
setTimeout(() => {
// The MutationObserver from the cdkObserveContent directive detected the content change
// and notified the slide-toggle component. The slide-toggle then marks the component as
// dirty by calling `markForCheck()`. This needs to be reflected by the component template
// then.
fixture.detectChanges();

expect(slideToggleElement.classList)
.not.toContain('mat-slide-toggle-bar-no-side-margin');
}, 1);
}));
});
});

describe('MdSlideToggle with forms', () => {
Expand Down Expand Up @@ -806,3 +866,10 @@ class SlideToggleWithFormControl {
template: `<md-slide-toggle tabindex="5"></md-slide-toggle>`
})
class SlideToggleWithTabindexAttr {}

@Component({
template: `<md-slide-toggle>{{label}}</md-slide-toggle>`
})
class SlideToggleWithoutLabel {
label: string;
}
7 changes: 7 additions & 0 deletions src/lib/slide-toggle/slide-toggle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,13 @@ export class MdSlideToggle extends _MdSlideToggleMixinBase implements OnDestroy,
}
}

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

/**
Expand Down

0 comments on commit c476c0a

Please sign in to comment.