Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions src/material/list/list-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ export abstract class MatListBase {
host: {
'[class.mdc-list-item--disabled]': 'disabled',
'[attr.aria-disabled]': 'disabled',
'[attr.disabled]': '(_isButtonElement && disabled) || null',
},
})
/** @docs-private */
Expand All @@ -98,6 +99,9 @@ export abstract class MatListItemBase implements AfterViewInit, OnDestroy, Rippl
/** Host element for the list item. */
_hostElement: HTMLElement;

/** indicate whether the host element is a button or not */
_isButtonElement: boolean;

/** Whether animations are disabled. */
_noopAnimations: boolean;

Expand Down Expand Up @@ -177,6 +181,7 @@ export abstract class MatListItemBase implements AfterViewInit, OnDestroy, Rippl
) {
this.rippleConfig = globalRippleOptions || {};
this._hostElement = this._elementRef.nativeElement;
this._isButtonElement = this._hostElement.nodeName.toLowerCase() === 'button';
this._noopAnimations = animationMode === 'NoopAnimations';

if (_listBase && !_listBase._isNonInteractive) {
Expand All @@ -186,10 +191,7 @@ export abstract class MatListItemBase implements AfterViewInit, OnDestroy, Rippl
// If no type attribute is specified for a host `<button>` element, set it to `button`. If a
// type attribute is already specified, we do nothing. We do this for backwards compatibility.
// TODO: Determine if we intend to continue doing this for the MDC-based list.
if (
this._hostElement.nodeName.toLowerCase() === 'button' &&
!this._hostElement.hasAttribute('type')
) {
if (this._isButtonElement && !this._hostElement.hasAttribute('type')) {
this._hostElement.setAttribute('type', 'button');
}
}
Expand Down
57 changes: 56 additions & 1 deletion src/material/list/list.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {fakeAsync, TestBed, waitForAsync} from '@angular/core/testing';
import {dispatchFakeEvent, dispatchMouseEvent} from '@angular/cdk/testing/private';
import {Component, QueryList, ViewChildren} from '@angular/core';
import {Component, QueryList, ViewChild, ViewChildren} from '@angular/core';
import {By} from '@angular/platform-browser';
import {MatListItem, MatListModule} from './index';

Expand All @@ -22,6 +22,8 @@ describe('MDC-based MatList', () => {
NavListWithActivatedItem,
ActionListWithoutType,
ActionListWithType,
ActionListWithDisabledList,
ActionListWithDisabledItem,
ListWithDisabledItems,
StandaloneListItem,
],
Expand Down Expand Up @@ -377,6 +379,34 @@ describe('MDC-based MatList', () => {
fixture.detectChanges();
}).not.toThrow();
});

it('should be able to disable and enable the entire action list', () => {
const fixture = TestBed.createComponent(ActionListWithDisabledList);
const listItems: HTMLElement[] = Array.from(
fixture.nativeElement.querySelectorAll('[mat-list-item]'),
);
fixture.detectChanges();

expect(listItems.every(listItem => listItem.hasAttribute('disabled'))).toBe(true);

fixture.componentInstance.disableList = false;
fixture.detectChanges();

expect(listItems.every(listItem => !listItem.hasAttribute('disabled'))).toBe(true);
});

it('should be able to disable and enable button item', () => {
const fixture = TestBed.createComponent(ActionListWithDisabledItem);
const buttonItem: HTMLButtonElement = fixture.nativeElement.querySelector('[mat-list-item]');
fixture.detectChanges();

expect(buttonItem.hasAttribute('disabled')).toBe(true);

fixture.componentInstance.buttonItem.disabled = false;
fixture.detectChanges();

expect(buttonItem.hasAttribute('disabled')).toBe(false);
});
});

class BaseTestList {
Expand Down Expand Up @@ -460,6 +490,31 @@ class ActionListWithType extends BaseTestList {
@ViewChildren(MatListItem) listItems: QueryList<MatListItem>;
}

@Component({
template: `
<mat-action-list [disabled]="disableList">
<button mat-list-item *ngFor="let item of items">
{{item.name}}
</button>
</mat-action-list>`,
})
class ActionListWithDisabledList extends BaseTestList {
disableList = true;
}

@Component({
template: `
<mat-action-list>
<button mat-list-item [disabled]="disableItem">
Paprika
</button>
</mat-action-list>`,
})
class ActionListWithDisabledItem extends BaseTestList {
@ViewChild(MatListItem) buttonItem: MatListItem;
disableItem = true;
}

@Component({
template: `
<mat-list>
Expand Down