From 49be5707776f5035d87a5ce8d3e3c73b43d2fb66 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Fri, 8 May 2020 21:45:33 +0200 Subject: [PATCH] fix(chips): chip list overriding chip disabled value (#19228) When a chip list is disabled, it goes through all the chips and sets their `disabled` values. The problem is that this overrides any individual values the consumer may have set. These changes fix the issue by saving the value to a different field. Fixes #19213. --- src/material/chips/chip-list.spec.ts | 22 +++++++++++++++++++++ src/material/chips/chip-list.ts | 2 +- src/material/chips/chip.ts | 23 +++++++++++++++------- tools/public_api_guard/material/chips.d.ts | 8 ++++++-- 4 files changed, 45 insertions(+), 10 deletions(-) diff --git a/src/material/chips/chip-list.spec.ts b/src/material/chips/chip-list.spec.ts index 09f0901fdce7..415039af19ae 100644 --- a/src/material/chips/chip-list.spec.ts +++ b/src/material/chips/chip-list.spec.ts @@ -112,6 +112,28 @@ describe('MatChipList', () => { expect(chips.toArray().every(chip => chip.disabled)).toBe(true); })); + it('should preserve the disabled state of a chip if the list gets re-enabled', () => { + const chipArray = chips.toArray(); + + chipArray[2].disabled = true; + fixture.detectChanges(); + + expect(chips.toArray().map(chip => chip.disabled)) + .toEqual([false, false, true, false, false]); + + chipListInstance.disabled = true; + fixture.detectChanges(); + + expect(chips.toArray().map(chip => chip.disabled)) + .toEqual([true, true, true, true, true]); + + chipListInstance.disabled = false; + fixture.detectChanges(); + + expect(chips.toArray().map(chip => chip.disabled)) + .toEqual([false, false, true, false, false]); + }); + }); describe('with selected chips', () => { diff --git a/src/material/chips/chip-list.ts b/src/material/chips/chip-list.ts index 832828b923c1..30572cc5b6d1 100644 --- a/src/material/chips/chip-list.ts +++ b/src/material/chips/chip-list.ts @@ -808,7 +808,7 @@ export class MatChipList extends _MatChipListMixinBase implements MatFormFieldCo private _syncChipsState() { if (this.chips) { this.chips.forEach(chip => { - chip.disabled = this._disabled; + chip._chipListDisabled = this._disabled; chip._chipListMultiple = this.multiple; }); } diff --git a/src/material/chips/chip.ts b/src/material/chips/chip.ts index fce39ac4ec7a..89054b501f52 100644 --- a/src/material/chips/chip.ts +++ b/src/material/chips/chip.ts @@ -29,8 +29,6 @@ import { import { CanColor, CanColorCtor, - CanDisable, - CanDisableCtor, CanDisableRipple, CanDisableRippleCtor, HasTabIndex, @@ -38,7 +36,6 @@ import { mixinTabIndex, MAT_RIPPLE_GLOBAL_OPTIONS, mixinColor, - mixinDisabled, mixinDisableRipple, RippleConfig, RippleGlobalOptions, @@ -71,12 +68,13 @@ export class MatChipSelectionChange { // Boilerplate for applying mixins to MatChip. /** @docs-private */ class MatChipBase { + disabled: boolean; constructor(public _elementRef: ElementRef) {} } -const _MatChipMixinBase: CanColorCtor & CanDisableRippleCtor & CanDisableCtor & +const _MatChipMixinBase: CanColorCtor & CanDisableRippleCtor & HasTabIndexCtor & typeof MatChipBase = - mixinTabIndex(mixinColor(mixinDisableRipple(mixinDisabled(MatChipBase)), 'primary'), -1); + mixinTabIndex(mixinColor(mixinDisableRipple(MatChipBase), 'primary'), -1); /** * Dummy directive to add CSS class to chip avatar. @@ -103,7 +101,7 @@ export class MatChipTrailingIcon {} */ @Directive({ selector: `mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]`, - inputs: ['color', 'disabled', 'disableRipple', 'tabIndex'], + inputs: ['color', 'disableRipple', 'tabIndex'], exportAs: 'matChip', host: { 'class': 'mat-chip mat-focus-indicator', @@ -124,7 +122,7 @@ export class MatChipTrailingIcon {} }, }) export class MatChip extends _MatChipMixinBase implements FocusableOption, OnDestroy, CanColor, - CanDisable, CanDisableRipple, RippleTarget, HasTabIndex { + CanDisableRipple, RippleTarget, HasTabIndex { /** Reference to the RippleRenderer for the chip. */ private _chipRipple: RippleRenderer; @@ -164,6 +162,9 @@ export class MatChip extends _MatChipMixinBase implements FocusableOption, OnDes /** Whether the chip list is in multi-selection mode. */ _chipListMultiple: boolean = false; + /** Whether the chip list as a whole is disabled. */ + _chipListDisabled: boolean = false; + /** The chip avatar */ @ContentChild(MatChipAvatar) avatar: MatChipAvatar; @@ -209,6 +210,14 @@ export class MatChip extends _MatChipMixinBase implements FocusableOption, OnDes } protected _selectable: boolean = true; + /** Whether the chip is disabled. */ + @Input() + get disabled(): boolean { return this._chipListDisabled || this._disabled; } + set disabled(value: boolean) { + this._disabled = coerceBooleanProperty(value); + } + protected _disabled: boolean = false; + /** * Determines whether or not the chip displays the remove styling and emits (removed) events. */ diff --git a/tools/public_api_guard/material/chips.d.ts b/tools/public_api_guard/material/chips.d.ts index 1b2a98ec3aa5..31b434eca948 100644 --- a/tools/public_api_guard/material/chips.d.ts +++ b/tools/public_api_guard/material/chips.d.ts @@ -1,8 +1,10 @@ export declare const MAT_CHIPS_DEFAULT_OPTIONS: InjectionToken; -export declare class MatChip extends _MatChipMixinBase implements FocusableOption, OnDestroy, CanColor, CanDisable, CanDisableRipple, RippleTarget, HasTabIndex { +export declare class MatChip extends _MatChipMixinBase implements FocusableOption, OnDestroy, CanColor, CanDisableRipple, RippleTarget, HasTabIndex { _animationsDisabled: boolean; + _chipListDisabled: boolean; _chipListMultiple: boolean; + protected _disabled: boolean; _elementRef: ElementRef; _hasFocus: boolean; readonly _onBlur: Subject; @@ -15,6 +17,8 @@ export declare class MatChip extends _MatChipMixinBase implements FocusableOptio avatar: MatChipAvatar; chipListSelectable: boolean; readonly destroyed: EventEmitter; + get disabled(): boolean; + set disabled(value: boolean); get removable(): boolean; set removable(value: boolean); removeIcon: MatChipRemove; @@ -46,7 +50,7 @@ export declare class MatChip extends _MatChipMixinBase implements FocusableOptio static ngAcceptInputType_removable: BooleanInput; static ngAcceptInputType_selectable: BooleanInput; static ngAcceptInputType_selected: BooleanInput; - static ɵdir: i0.ɵɵDirectiveDefWithMeta; + static ɵdir: i0.ɵɵDirectiveDefWithMeta; static ɵfac: i0.ɵɵFactoryDef; }