Skip to content
This repository has been archived by the owner on Oct 7, 2020. It is now read-only.

Commit

Permalink
feat(tabs): Add disabled tab + improvements
Browse files Browse the repository at this point in the history
Closes #349 Closes #147
  • Loading branch information
trimox committed Nov 9, 2017
1 parent 7ba346a commit 84f1665
Show file tree
Hide file tree
Showing 2 changed files with 143 additions and 11 deletions.
68 changes: 65 additions & 3 deletions src/demo-app/components/tab-demo/tab-demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ <h1 mdc-typography-display1>Tabs</h1>
<td>active: boolean</td>
<td>Whether or not the tab is active. Setting this makes the tab active.</td>
</tr>
<tr>
<td>disabled: boolean</td>
<td>Whether or not the tab is disabled. Setting this makes the tab disabled.</td>
</tr>
<tr>
<td>preventsDefaultOnClick: boolean</td>
<td>Whether or not the tab will call preventDefault() on an event. Setting this makes the tab call preventDefault() on events.</td>
Expand All @@ -85,6 +89,42 @@ <h1 mdc-typography-display1>Tabs</h1>
<td>Text and icon are centered horizontally in the tab.</td>
</tr>
</tbody>
<thead>
<tr>
<th>Methods</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>getComputedWidth(): number</td>
<td>Return the computed width for tab.</td>
</tr>
<tr>
<td>getComputedLeft(): number</td>
<td>Return the computed left offset for tab.</td>
</tr>
<tr>
<td>isActive()</td>
<td>Return true if tab is active.</td>
</tr>
<tr>
<td>setActive(boolean)</td>
<td>Set tab to active. If isActive is true, adds the active modifier class, otherwise removes it.</td>
</tr>
<tr>
<td>preventDefaultOnClick(): boolean</td>
<td>Return true if the tab prevents the default click action.</td>
</tr>
<tr>
<td>setPreventDefaultOnClick(boolean)</td>
<td>Sets tabs preventDefaultOnClick property to the value of the preventDefaultOnClick argument passed.</td>
</tr>
<tr>
<td>measureSelf()</td>
<td>Sets computedWidth and computedLeft for a tab.</td>
</tr>
</tbody>
<thead>
<tr>
<th>Events</th>
Expand All @@ -93,7 +133,7 @@ <h1 mdc-typography-display1>Tabs</h1>
</thead>
<tbody>
<tr>
<td><pre>select(tab: TabComponent)</pre></td>
<td>select(tab: TabComponent)</td>
<td>Broadcast when a user actions on the tab.</td>
</tr>
</tbody>
Expand Down Expand Up @@ -282,8 +322,30 @@ <h1 mdc-typography-display1>Tabs</h1>
<span style="color:#89bdff">&lt;/<span style="color:#89bdff">mdc</span><span style="color:#89bdff">-tab</span>></span>
<span style="color:#89bdff">&lt;/<span style="color:#89bdff">mdc</span><span style="color:#89bdff">-tab-bar</span>></span>
</pre>
<div>
<span mdc-typography-headline>Dynamic view switching</span>

<div style="width: 50%;">
<span mdc-typography-headline>Toolbar with Tabs</span>

<mdc-toolbar>
<mdc-toolbar-row>
<mdc-toolbar-section [alignStart]="true">
<mdc-toolbar-title>App Title</mdc-toolbar-title>
</mdc-toolbar-section>
<mdc-toolbar-section [alignEnd]="true" [shrinkToFit]="false">
<mdc-tab-bar>
<mdc-tab>
<mdc-icon>phone</mdc-icon>
<mdc-tab-icon-text>Recents</mdc-tab-icon-text>
</mdc-tab>
<mdc-tab>
<mdc-icon>favorite</mdc-icon>
<mdc-tab-icon-text>Favorites</mdc-tab-icon-text>
</mdc-tab>
</mdc-tab-bar>
</mdc-toolbar-section>
</mdc-toolbar-row>
</mdc-toolbar>

<mdc-tab-bar>
<mdc-tab *ngFor="let tabLink of tabLinks" [routerLink]="[{outlets: {taboutlet: tabLink.link}}]" [active]="tabLink.active">{{tabLink.label}}</mdc-tab>
</mdc-tab-bar>
Expand Down
86 changes: 78 additions & 8 deletions src/lib/tabs/tab/tab.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,35 @@
import {
AfterViewInit,
ContentChild,
Component,
ContentChild,
Directive,
ElementRef,
EventEmitter,
HostBinding,
Input,
OnChanges,
OnDestroy,
Output,
Renderer2,
SimpleChange,
TemplateRef,
ViewChild,
ViewContainerRef,
ViewEncapsulation,
} from '@angular/core';
import { toBoolean } from '../../common';
import { EventRegistry } from '../../common/event-registry';
import { MdcIcon } from '../../icon/icon';
import { MdcRipple } from '../../core/ripple/ripple.service';
import { TemplatePortal } from '../../cdk/portal';

import { MDCTabAdapter } from './adapter';
import { MDCTabFoundation } from '@material/tabs';

export class MdcTabSelect {
tab: MdcTab;
}

@Directive({
selector: '[mdc-tab-icon-text], mdc-tab-icon-text'
})
Expand All @@ -38,10 +48,26 @@ export class MdcTabIconText {
],
encapsulation: ViewEncapsulation.None,
})
export class MdcTab implements AfterViewInit, OnDestroy {
export class MdcTab implements AfterViewInit, OnChanges, OnDestroy {
/** Template inside the MdcTab view that contains an <ng-content>. */
@ViewChild(TemplateRef) _content: TemplateRef<any>;

/** The portal that will be the hosted content of the tab */
private _contentPortal: TemplatePortal<any> | null = null;
get content(): TemplatePortal<any> | null { return this._contentPortal; }

private _active: boolean = false;
private _disabled: boolean = false;

@Input()
get disabled(): boolean { return this._disabled; }
set disabled(value: boolean) {
this._disabled = value;
}
@Input()
get active(): boolean { return this.foundation.isActive(); }
get active(): boolean { return this._active; }
set active(value: boolean) {
this._active = value;
this.foundation.setActive(value);
}
@Input()
Expand All @@ -54,14 +80,18 @@ export class MdcTab implements AfterViewInit, OnDestroy {
set disableRipple(value: boolean) {
this.ripple.disabled = toBoolean(value);
}
@Output() select: EventEmitter<{ tab: MdcTab }> = new EventEmitter();
@Output() select: EventEmitter<MdcTabSelect> = new EventEmitter();
@Output() disableChange: EventEmitter<MdcTabSelect> = new EventEmitter();
@HostBinding('class.mdc-tab') isHostClass = true;
@HostBinding('attr.role') role: string = 'tab';
@HostBinding('class.mdc-tab--with-icon-and-text') get classIconText() {
return this.tabIcon != null && this.tabIconText != null;
}
@HostBinding('class.mdc-tab--active') get classActive() {
return this.foundation.isActive();
return this._active ? 'mdc-tab--active' : '';
}
@HostBinding('class.mdc-tab--disabled') get classDisabled() {
return this._disabled ? 'mdc-tab--disabled' : '';
}
@ContentChild(MdcIcon) tabIcon: MdcIcon;
@ContentChild(MdcTabIconText) tabIconText: MdcTabIconText;
Expand Down Expand Up @@ -97,21 +127,61 @@ export class MdcTab implements AfterViewInit, OnDestroy {
} = new MDCTabFoundation(this._mdcAdapter);

constructor(
private _viewContainerRef: ViewContainerRef,
private _renderer: Renderer2,
public elementRef: ElementRef,
private _registry: EventRegistry,
public ripple: MdcRipple) {
this.ripple.init();
}

ngAfterViewInit(): void {
this.foundation.init();
if (this.tabIcon) {
ngOnChanges(changes: { [key: string]: SimpleChange }): void {
const disabled = changes['mdcDrawerSelected'];
const tabIcon = changes['tabIcon'];

if (disabled) {
this.disableChange.emit({ tab: this });
}
if (tabIcon) {
this._renderer.addClass(this.tabIcon.elementRef.nativeElement, 'mdc-tab__icon');
}
}

ngAfterViewInit(): void {
this.foundation.init();
this._contentPortal = new TemplatePortal(this._content, this._viewContainerRef);
this.setPreventDefaultOnClick(true);
}

ngOnDestroy(): void {
this.foundation.destroy();
}

isActive(): boolean {
return this._active;
}

setActive(value: boolean): void {
this._active = value;
}

getComputedWidth(): number {
return this.foundation.getComputedWidth();
}

getComputedLeft(): number {
return this._mdcAdapter.getOffsetLeft();
}

preventDefaultOnClick(): boolean {
return this.foundation.preventsDefaultOnClick();
}

setPreventDefaultOnClick(value: boolean): void {
this.foundation.setPreventDefaultOnClick(value);
}

measureSelf(): void {
this.foundation.measureSelf();
}
}

0 comments on commit 84f1665

Please sign in to comment.