diff --git a/src/lib/toolbar/index.ts b/src/lib/toolbar/index.ts index eb66854ca316..2b8be90eca30 100644 --- a/src/lib/toolbar/index.ts +++ b/src/lib/toolbar/index.ts @@ -7,12 +7,13 @@ */ import {NgModule} from '@angular/core'; +import {PlatformModule} from '@angular/cdk/platform'; import {MdCommonModule} from '../core'; import {MdToolbar, MdToolbarRow} from './toolbar'; @NgModule({ - imports: [MdCommonModule], + imports: [MdCommonModule, PlatformModule], exports: [MdToolbar, MdToolbarRow, MdCommonModule], declarations: [MdToolbar, MdToolbarRow], }) diff --git a/src/lib/toolbar/toolbar.html b/src/lib/toolbar/toolbar.html index e81e16e5d708..208f30d2edaa 100644 --- a/src/lib/toolbar/toolbar.html +++ b/src/lib/toolbar/toolbar.html @@ -1,5 +1,5 @@
- + diff --git a/src/lib/toolbar/toolbar.md b/src/lib/toolbar/toolbar.md index eb7189923d0f..11826b4f6c76 100644 --- a/src/lib/toolbar/toolbar.md +++ b/src/lib/toolbar/toolbar.md @@ -21,6 +21,19 @@ Each toolbar row is a `display: flex` container. ``` +In some situations, developers need full control over all `` elements +(e.g. for use with flex-layout). + +To have full control over the first ``, which is usually auto-generated, +there should be only row elements in the ``. + +```html + + First Row + Second Row + +``` + ### Positioning toolbar content The toolbar does not perform any positioning of its content. This gives the user full power to position the content as it suits their application. diff --git a/src/lib/toolbar/toolbar.spec.ts b/src/lib/toolbar/toolbar.spec.ts index 6e0c6d4da7cd..681b6ed12457 100644 --- a/src/lib/toolbar/toolbar.spec.ts +++ b/src/lib/toolbar/toolbar.spec.ts @@ -3,55 +3,86 @@ import {TestBed, async, ComponentFixture} from '@angular/core/testing'; import {By} from '@angular/platform-browser'; import {MdToolbarModule} from './index'; - describe('MdToolbar', () => { - let fixture: ComponentFixture; - let testComponent: TestApp; - let toolbarElement: HTMLElement; - beforeEach(async(() => { TestBed.configureTestingModule({ imports: [MdToolbarModule], - declarations: [TestApp], + declarations: [ToolbarWithDefaultFirstRow, ToolbarWithoutDefaultFirstRow], }); TestBed.compileComponents(); })); - beforeEach(() => { - fixture = TestBed.createComponent(TestApp); - testComponent = fixture.debugElement.componentInstance; - toolbarElement = fixture.debugElement.query(By.css('md-toolbar')).nativeElement; - }); + describe('with default first row', () => { + let fixture: ComponentFixture; + let testComponent: ToolbarWithDefaultFirstRow; + let toolbarElement: HTMLElement; + let toolbarRowElements: HTMLElement[]; + + beforeEach(() => { + fixture = TestBed.createComponent(ToolbarWithDefaultFirstRow); + testComponent = fixture.debugElement.componentInstance; + toolbarElement = fixture.debugElement.query(By.css('.mat-toolbar')).nativeElement; + toolbarRowElements = fixture.debugElement.queryAll(By.css('.mat-toolbar-row')) + .map(rowDebugElement => rowDebugElement.nativeElement); + }); - it('should apply class based on color attribute', () => { - testComponent.toolbarColor = 'primary'; - fixture.detectChanges(); + it('should apply class based on color attribute', () => { + testComponent.toolbarColor = 'primary'; + fixture.detectChanges(); - expect(toolbarElement.classList.contains('mat-primary')).toBe(true); + expect(toolbarElement.classList.contains('mat-primary')).toBe(true); - testComponent.toolbarColor = 'accent'; - fixture.detectChanges(); + testComponent.toolbarColor = 'accent'; + fixture.detectChanges(); - expect(toolbarElement.classList.contains('mat-primary')).toBe(false); - expect(toolbarElement.classList.contains('mat-accent')).toBe(true); + expect(toolbarElement.classList.contains('mat-primary')).toBe(false); + expect(toolbarElement.classList.contains('mat-accent')).toBe(true); + + testComponent.toolbarColor = 'warn'; + fixture.detectChanges(); + + expect(toolbarElement.classList.contains('mat-accent')).toBe(false); + expect(toolbarElement.classList.contains('mat-warn')).toBe(true); + }); - testComponent.toolbarColor = 'warn'; - fixture.detectChanges(); + it('should set the toolbar role on the host', () => { + expect(toolbarElement.getAttribute('role')).toBe('toolbar'); + }); - expect(toolbarElement.classList.contains('mat-accent')).toBe(false); - expect(toolbarElement.classList.contains('mat-warn')).toBe(true); + it('should generate a default first row if content is projected', () => { + expect(toolbarRowElements.length) + .toBe(2, 'Expected a default first row and a second row to be present.'); + }); }); - it('should set the toolbar role on the host', () => { - expect(toolbarElement.getAttribute('role')).toBe('toolbar'); + describe('without default first row', () => { + + it('should not generate a default first row if no content is projected', () => { + const fixture = TestBed.createComponent(ToolbarWithoutDefaultFirstRow); + + expect(fixture.debugElement.queryAll(By.css('.mat-toolbar-row')).length) + .toBe(2, 'Expected one toolbar row to be present while no content is projected.'); + }); }); + }); -@Component({template: `Test Toolbar`}) -class TestApp { +@Component({template: ` + + First Row + Second Row + `}) +class ToolbarWithDefaultFirstRow { toolbarColor: string; } + +@Component({template: ` + + First Row + +`}) +class ToolbarWithoutDefaultFirstRow {} diff --git a/src/lib/toolbar/toolbar.ts b/src/lib/toolbar/toolbar.ts index 772869c8fadb..c98f9b6fb052 100644 --- a/src/lib/toolbar/toolbar.ts +++ b/src/lib/toolbar/toolbar.ts @@ -13,15 +13,11 @@ import { Directive, ElementRef, Renderer2, + ViewChild, + AfterViewInit, } from '@angular/core'; import {CanColor, mixinColor} from '../core/common-behaviors/color'; - - -@Directive({ - selector: 'md-toolbar-row, mat-toolbar-row', - host: {'class': 'mat-toolbar-row'}, -}) -export class MdToolbarRow {} +import {Platform} from '@angular/cdk/platform'; // Boilerplate for applying mixins to MdToolbar. /** @docs-private */ @@ -30,7 +26,6 @@ export class MdToolbarBase { } export const _MdToolbarMixinBase = mixinColor(MdToolbarBase); - @Component({ moduleId: module.id, selector: 'md-toolbar, mat-toolbar', @@ -44,10 +39,35 @@ export const _MdToolbarMixinBase = mixinColor(MdToolbarBase); changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None }) -export class MdToolbar extends _MdToolbarMixinBase implements CanColor { +export class MdToolbar extends _MdToolbarMixinBase implements CanColor, AfterViewInit { - constructor(renderer: Renderer2, elementRef: ElementRef) { + /** Element reference to the default first row of the toolbar. */ + @ViewChild('defaultFirstRow', { read: ElementRef }) _defaultFirstRow: ElementRef; + + constructor(renderer: Renderer2, elementRef: ElementRef, private _platform: Platform) { super(renderer, elementRef); } + ngAfterViewInit() { + // Do nothing if we're not on the browser platform. + if (!this._platform.isBrowser) { + return; + } + + const firstRowElement = this._defaultFirstRow.nativeElement; + + // If the first toolbar row, which will be auto-generated, does not have any projected content, + // then the auto-generated first toolbar row should be removed. This gives developers + // full control over the first toolbar row (e.g. for use with flex-layout). + if (!firstRowElement.innerHTML.trim()) { + firstRowElement.parentNode.removeChild(firstRowElement); + } + } } + +@Directive({ + selector: 'md-toolbar-row, mat-toolbar-row', + host: {'class': 'mat-toolbar-row'}, +}) +export class MdToolbarRow {} +