feat(autocomplete): add md-autocomplete classes to overlay panel (#7176)

Transfers any classes added to `md-autocomplete` to the resulting panel, allowing for easier styling similarly to `md-menu`.

Fixes #4196.
This commit is contained in:
Kristiyan Kostadinov
2017-09-29 22:10:18 +02:00
committed by Andrew Seguin
parent 2d350a0893
commit f8cd7906ff
3 changed files with 37 additions and 12 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
<ng-template>
<div class="mat-autocomplete-panel" role="listbox" [id]="id" [ngClass]="_getClassList()" #panel>
<div class="mat-autocomplete-panel" role="listbox" [id]="id" [ngClass]="_classList" #panel>
<ng-content></ng-content>
</div>
</ng-template>
+20 -1
View File
@@ -1521,6 +1521,25 @@ describe('MatAutocomplete', () => {
expect(placeholder.classList).not.toContain('mat-form-field-empty');
}));
it('should transfer the mat-autocomplete classes to the panel element', fakeAsync(() => {
const fixture = TestBed.createComponent(SimpleAutocomplete);
fixture.detectChanges();
fixture.componentInstance.trigger.openPanel();
tick();
fixture.detectChanges();
const autocomplete = fixture.debugElement.nativeElement.querySelector('mat-autocomplete');
const panel = overlayContainerElement.querySelector('.mat-autocomplete-panel')!;
expect(autocomplete.classList).not.toContain('class-one');
expect(autocomplete.classList).not.toContain('class-two');
expect(panel.classList).toContain('class-one');
expect(panel.classList).toContain('class-two');
}));
});
it('should have correct width when opened', () => {
@@ -1646,7 +1665,7 @@ describe('MatAutocomplete', () => {
<input matInput placeholder="State" [matAutocomplete]="auto" [formControl]="stateCtrl">
</mat-form-field>
<mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn">
<mat-autocomplete class="class-one class-two" #auto="matAutocomplete" [displayWith]="displayFn">
<mat-option *ngFor="let state of filteredStates" [value]="state">
<span> {{ state.code }}: {{ state.name }} </span>
</mat-option>
+16 -10
View File
@@ -77,10 +77,23 @@ export class MatAutocomplete implements AfterContentInit {
@Output() optionSelected: EventEmitter<MatAutocompleteSelectedEvent> =
new EventEmitter<MatAutocompleteSelectedEvent>();
/**
* Takes classes set on the host md-autocomplete element and applies them to the panel
* inside the overlay container to allow for easy styling.
*/
@Input('class')
set classList(classList: string) {
if (classList && classList.length) {
classList.split(' ').forEach(className => this._classList[className.trim()] = true);
this._elementRef.nativeElement.className = '';
}
}
_classList: {[key: string]: boolean} = {};
/** Unique ID to be used by autocomplete trigger's "aria-owns" property. */
id: string = `mat-autocomplete-${_uniqueAutocompleteIdCounter++}`;
constructor(private _changeDetectorRef: ChangeDetectorRef) { }
constructor(private _changeDetectorRef: ChangeDetectorRef, private _elementRef: ElementRef) { }
ngAfterContentInit() {
this._keyManager = new ActiveDescendantKeyManager<MatOption>(this.options).withWrap();
@@ -105,6 +118,8 @@ export class MatAutocomplete implements AfterContentInit {
_setVisibility(): void {
Promise.resolve().then(() => {
this.showPanel = !!this.options.length;
this._classList['mat-autocomplete-visible'] = this.showPanel;
this._classList['mat-autocomplete-hidden'] = !this.showPanel;
this._changeDetectorRef.markForCheck();
});
}
@@ -114,14 +129,5 @@ export class MatAutocomplete implements AfterContentInit {
const event = new MatAutocompleteSelectedEvent(this, option);
this.optionSelected.emit(event);
}
/** Sets a class on the panel based on whether it is visible. */
_getClassList() {
return {
'mat-autocomplete-visible': this.showPanel,
'mat-autocomplete-hidden': !this.showPanel
};
}
}