-
Notifications
You must be signed in to change notification settings - Fork 6.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(select): add md-select-header directive #3211
Changes from all commits
2420398
6df224b
57534ae
498c569
6f6297e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -113,5 +113,20 @@ | |
</md-card> | ||
</div> | ||
|
||
<md-card *ngIf="showSelect"> | ||
<md-select placeholder="Drink" [(ngModel)]="currentDrink" #selectWitHeader="mdSelect"> | ||
<md-select-header> | ||
<input type="search" [(ngModel)]="searchTerm" role="combobox" [attr.aria-owns]="selectWitHeader.panelId" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did you try this out in a screen reader w/ this role/aria-owns? I'm not sure it will work as expected |
||
(ngModelChange)="filterDrinks()" placeholder="Search for a drink"/> | ||
</md-select-header> | ||
|
||
<md-option *ngFor="let drink of filteredDrinks" [value]="drink.value" [disabled]="drink.disabled"> | ||
{{ drink.viewValue }} | ||
</md-option> | ||
|
||
</md-select> | ||
</md-card> | ||
|
||
|
||
</div> | ||
<div style="height: 500px">This div is for testing scrolled selects.</div> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/** No CSS for this example */ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<md-select placeholder="Favorite food" [(ngModel)]="selectedValue" name="food" #select="mdSelect"> | ||
<md-select-header> | ||
<input type="search" [(ngModel)]="searchString" role="combobox" [attr.aria-owns]="select.panelId" | ||
(ngModelChange)="filterFoods()" placeholder="Search for food"/> | ||
</md-select-header> | ||
|
||
<md-option *ngFor="let food of foods" [value]="food.value"> | ||
{{food.viewValue}} | ||
</md-option> | ||
</md-select> | ||
|
||
<p> Selected value: {{selectedValue}} </p> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import {Component} from '@angular/core'; | ||
|
||
|
||
@Component({ | ||
selector: 'select-form-example', | ||
templateUrl: './select-form-example.html', | ||
}) | ||
export class SelectHeaderExample { | ||
selectedValue: string; | ||
searchString: string; | ||
|
||
initialFoods = [ | ||
{ value: 'steak-0', viewValue: 'Steak' }, | ||
{ value: 'pizza-1', viewValue: 'Pizza' }, | ||
{ value: 'tacos-2', viewValue: 'Tacos' }, | ||
{ value: 'sandwich-3', viewValue: 'Sandwich' }, | ||
{ value: 'chips-4', viewValue: 'Chips' }, | ||
{ value: 'eggs-5', viewValue: 'Eggs' }, | ||
{ value: 'pasta-6', viewValue: 'Pasta' }, | ||
{ value: 'sushi-7', viewValue: 'Sushi' }, | ||
]; | ||
|
||
foods = this.initialFoods.slice(); | ||
|
||
filterFoods() { | ||
this.foods = this.searchString ? this.initialFoods.filter(item => { | ||
return item.viewValue.toLowerCase().indexOf(this.searchString.toLowerCase()) > -1; | ||
}) : this.initialFoods.slice(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/** | ||
* @license | ||
* Copyright Google Inc. All Rights Reserved. | ||
* | ||
* Use of this source code is governed by an MIT-style license that can be | ||
* found in the LICENSE file at https://angular.io/license | ||
*/ | ||
|
||
import {Directive} from '@angular/core'; | ||
|
||
|
||
/** | ||
* Fixed header that will be rendered above a select's options. | ||
*/ | ||
@Directive({ | ||
selector: 'md-select-header, mat-select-header', | ||
host: { | ||
'class': 'mat-select-header', | ||
} | ||
}) | ||
export class MdSelectHeader { } |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,7 +35,12 @@ | |
[style.transformOrigin]="_transformOrigin" | ||
[class.mat-select-panel-done-animating]="_panelDoneAnimating"> | ||
|
||
<div class="mat-select-content" [@fadeInContent]="'showing'" (@fadeInContent.done)="_onFadeInDone()"> | ||
<div [@fadeInContent]="'showing'"> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you could replace this |
||
<ng-content select="md-select-header, mat-select-header"></ng-content> | ||
</div> | ||
|
||
<div class="mat-select-content" [attr.id]="panelId" [@fadeInContent]="'showing'" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think just |
||
(@fadeInContent.done)="_onFadeInDone()"> | ||
<ng-content></ng-content> | ||
</div> | ||
</div> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -117,14 +117,33 @@ $mat-select-panel-max-height: 256px !default; | |
margin: 0 $mat-select-arrow-margin; | ||
} | ||
|
||
.mat-select-panel { | ||
@include mat-menu-base(); | ||
padding-top: 0; | ||
padding-bottom: 0; | ||
.mat-select-content { | ||
@include mat-menu-scrollable(); | ||
max-height: $mat-select-panel-max-height; | ||
min-width: 100%; // prevents some animation twitching and test inconsistencies in IE11 | ||
|
||
@include cdk-high-contrast { | ||
outline: solid 1px; | ||
} | ||
} | ||
|
||
.mat-select-panel { | ||
@include mat-menu-base(); | ||
border: none; | ||
} | ||
|
||
.mat-select-header { | ||
@include mat-menu-item-base(); | ||
border-bottom: solid 1px; | ||
box-sizing: border-box; | ||
|
||
input { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd lean toward omitting this style in the select itself, since the select header is mean to be a generic container that's not necessarily used for this style of filter (even if that is the most common use case) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The issue with allowing anything inside the header is that, with the way it is currently set up, the positioning won't work with anything that isn't 48px high. Alternatively, I can hard-code the header height. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd rather do that for now and then revisit the positioning to make it more flexible in the future. |
||
display: block; | ||
width: 100%; | ||
height: 100%; | ||
border: none; | ||
outline: none; | ||
padding: 0; | ||
background: transparent; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this demo, if I select a value and then try to type into the input then the focus leaves the text input on every keypress
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm you're right. This complicates things a lot, because it means that we'd need two different key handling strategies depending on whether the select has a header (
FocusKeyManager
by default andActiveDescendantKeyManager
if there's a header), which in turn will complicate the select even more, because it would have to delegate to the header in some cases but not in others. I can see how it can turn into a huge mess pretty quickly since we'd need to sprinkleif (this.header)
all over the place and there would be aMdSelect <-> MdSelectHeader
dependency. It might be best if we park and rethink whether we want to do this or recommend that people usemd-autocomplete
instead.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just not this, please, searching is not the sole use case for the select header and even if it was, autocomplete has it's own problems that make it hard to use as a select.. #3334