From 7f0f473bd4e4ab45c19f1cb4bdd9fb8e9167963f Mon Sep 17 00:00:00 2001 From: Paul Gschwendtner Date: Fri, 21 Apr 2017 18:33:21 +0200 Subject: [PATCH] feat(list): option to disable ripples for all items (#4159) Fixes #4149. --- src/lib/list/index.ts | 3 -- src/lib/list/list.spec.ts | 31 ++++++++++++++++---- src/lib/list/list.ts | 62 +++++++++++++++++++-------------------- 3 files changed, 55 insertions(+), 41 deletions(-) diff --git a/src/lib/list/index.ts b/src/lib/list/index.ts index 0afe8ac61e30..23f9800ecc41 100644 --- a/src/lib/list/index.ts +++ b/src/lib/list/index.ts @@ -10,7 +10,6 @@ import { MdNavListCssMatStyler, MdDividerCssMatStyler, MdListSubheaderCssMatStyler, - MdNavListTokenSetter, } from './list'; @@ -28,7 +27,6 @@ import { MdNavListCssMatStyler, MdDividerCssMatStyler, MdListSubheaderCssMatStyler, - MdNavListTokenSetter, ], declarations: [ MdList, @@ -40,7 +38,6 @@ import { MdNavListCssMatStyler, MdDividerCssMatStyler, MdListSubheaderCssMatStyler, - MdNavListTokenSetter, ], }) export class MdListModule { diff --git a/src/lib/list/list.spec.ts b/src/lib/list/list.spec.ts index b7a46ec95cdb..57593122cd00 100644 --- a/src/lib/list/list.spec.ts +++ b/src/lib/list/list.spec.ts @@ -125,17 +125,35 @@ describe('MdList', () => { items.forEach(item => expect(item.isRippleEnabled()).toBe(false)); }); - it('should maybe show ripples for nav lists', () => { + it('should allow disabling ripples for specific nav-list items', () => { let fixture = TestBed.createComponent(NavListWithOneAnchorItem); fixture.detectChanges(); - const items: QueryList = fixture.debugElement.componentInstance.listItems; + const items = fixture.componentInstance.listItems; + expect(items.length).toBeGreaterThan(0); + + // Ripples should be enabled by default, and can be disabled with a binding. + items.forEach(item => expect(item.isRippleEnabled()).toBe(true)); + + fixture.componentInstance.disableItemRipple = true; + fixture.detectChanges(); + + items.forEach(item => expect(item.isRippleEnabled()).toBe(false)); + }); + + it('should allow disabling ripples for the whole nav-list', () => { + let fixture = TestBed.createComponent(NavListWithOneAnchorItem); + fixture.detectChanges(); + + const items = fixture.componentInstance.listItems; expect(items.length).toBeGreaterThan(0); + // Ripples should be enabled by default, and can be disabled with a binding. items.forEach(item => expect(item.isRippleEnabled()).toBe(true)); - fixture.debugElement.componentInstance.disableRipple = true; + fixture.componentInstance.disableListRipple = true; fixture.detectChanges(); + items.forEach(item => expect(item.isRippleEnabled()).toBe(false)); }); }); @@ -163,14 +181,15 @@ class ListWithOneAnchorItem extends BaseTestList { } @Component({template: ` - - + + Paprika `}) class NavListWithOneAnchorItem extends BaseTestList { @ViewChildren(MdListItem) listItems: QueryList; - disableRipple: boolean = false; + disableItemRipple: boolean = false; + disableListRipple: boolean = false; } @Component({template: ` diff --git a/src/lib/list/list.ts b/src/lib/list/list.ts index 5a7df8fe1d76..d21f296d8386 100644 --- a/src/lib/list/list.ts +++ b/src/lib/list/list.ts @@ -6,29 +6,18 @@ import { QueryList, Directive, ElementRef, - Inject, Input, - OpaqueToken, Optional, Renderer, AfterContentInit, } from '@angular/core'; -import {MdLine, MdLineSetter} from '../core'; +import {MdLine, MdLineSetter, coerceBooleanProperty} from '../core'; @Directive({ selector: 'md-divider, mat-divider' }) export class MdListDivider {} -/** - * Token used to inject the list type into child MdListItem components so they can know whether - * they're in a nav list (and thus should use an MdRipple). - */ -export const LIST_TYPE_TOKEN = new OpaqueToken('list_type'); - -const NORMAL_LIST_TYPE = 'normal_list_type'; -const NAV_LIST_TYPE = 'nav_list_type'; - @Component({ moduleId: module.id, selector: 'md-list, mat-list, md-nav-list, mat-nav-list', @@ -36,10 +25,19 @@ const NAV_LIST_TYPE = 'nav_list_type'; 'role': 'list'}, template: '', styleUrls: ['list.css'], - providers: [{ provide: LIST_TYPE_TOKEN, useValue: NORMAL_LIST_TYPE }], encapsulation: ViewEncapsulation.None }) -export class MdList {} +export class MdList { + private _disableRipple: boolean = false; + + /** + * Whether the ripple effect should be disabled on the list-items or not. + * This flag only has an effect for `md-nav-list` components. + */ + @Input() + get disableRipple() { return this._disableRipple; } + set disableRipple(value: boolean) { this._disableRipple = coerceBooleanProperty(value); } +} /** * Directive whose purpose is to add the mat- CSS styling to this selector. @@ -65,15 +63,6 @@ export class MdListCssMatStyler {} }) export class MdNavListCssMatStyler {} -/** - * Directive to set the ListType token to NAV_LIST_TYPE. - */ -@Directive({ - selector: 'md-nav-list, mat-nav-list', - providers: [{ provide: LIST_TYPE_TOKEN, useValue: NAV_LIST_TYPE }], -}) -export class MdNavListTokenSetter {} - /** * Directive whose purpose is to add the mat- CSS styling to this selector. * @docs-private @@ -135,14 +124,19 @@ export class MdListSubheaderCssMatStyler {} encapsulation: ViewEncapsulation.None }) export class MdListItem implements AfterContentInit { - /** - * Whether the ripple effect on click should be disabled. This applies only to list items that - * are children of an md-nav-list; md-list items never have ripples. - */ - @Input() disableRipple: boolean = false; + private _lineSetter: MdLineSetter; + private _disableRipple: boolean = false; + private _isNavList: boolean = false; + _hasFocus: boolean = false; - private _lineSetter: MdLineSetter; + /** + * Whether the ripple effect on click should be disabled. This applies only to list items that are + * part of a nav list. The value of `disableRipple` on the `md-nav-list` overrides this flag. + */ + @Input() + get disableRipple() { return this._disableRipple; } + set disableRipple(value: boolean) { this._disableRipple = coerceBooleanProperty(value); } @ContentChildren(MdLine) _lines: QueryList; @@ -152,8 +146,12 @@ export class MdListItem implements AfterContentInit { this._element.nativeElement, 'mat-list-item-avatar', avatar != null); } - constructor(private _renderer: Renderer, private _element: ElementRef, - @Optional() @Inject(LIST_TYPE_TOKEN) private _listType: string) {} + constructor(private _renderer: Renderer, + private _element: ElementRef, + @Optional() private _list: MdList, + @Optional() navList: MdNavListCssMatStyler) { + this._isNavList = !!navList; + } ngAfterContentInit() { this._lineSetter = new MdLineSetter(this._lines, this._renderer, this._element); @@ -161,7 +159,7 @@ export class MdListItem implements AfterContentInit { /** Whether this list item should show a ripple effect when clicked. */ isRippleEnabled() { - return !this.disableRipple && (this._listType === NAV_LIST_TYPE); + return !this.disableRipple && this._isNavList && !this._list.disableRipple; } _handleFocus() {