Skip to content
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): make select work inside form-field #6488

Merged
merged 27 commits into from
Sep 21, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
4656ab4
strip down select DOM and implement MdFormFieldControl
mmalerba Aug 14, 2017
80b65d5
tweak select styles to fit form-field
mmalerba Aug 14, 2017
8ff539f
make dropdown adjust to form field's font size (still 1px rounding erorr
mmalerba Aug 15, 2017
9ef3503
fix 1px jitter and baseline alignment
mmalerba Aug 15, 2017
21c6701
finish up MdFormFieldControl implementation
mmalerba Aug 15, 2017
272a762
fix floating placehodler and color
mmalerba Aug 15, 2017
bb43366
fix overlay font size on safari
mmalerba Aug 15, 2017
6abca5a
fix width on firefox
mmalerba Aug 15, 2017
fd27cd1
open select when form field is clicked
mmalerba Aug 16, 2017
face17e
separate the "floating" logic from the "empty" logic
mmalerba Aug 16, 2017
327c04b
fix slight error in multi-select dropdown placement
mmalerba Aug 16, 2017
9626eb1
exclude hint and error from focusing select on click
mmalerba Aug 17, 2017
d1132f2
add some fancy form-field features to select demo
mmalerba Aug 17, 2017
2d4cb62
add a class to form-field depending on the control type for easy styling
mmalerba Aug 17, 2017
b660ddf
fix most tests, exceptions noted with TODOs
mmalerba Aug 18, 2017
e0d2c06
fix prerender and input test
mmalerba Aug 19, 2017
07e15a2
make placeholder float when select is opened, and prevent it from ove…
mmalerba Aug 19, 2017
db019d2
fix remaining tests
mmalerba Aug 20, 2017
9c9e932
fix lint
mmalerba Aug 21, 2017
6ec117e
clean up measurement logic
mmalerba Aug 21, 2017
9cc3837
fix rebase issues
mmalerba Aug 21, 2017
9c3f905
fix remaining demos and examples
mmalerba Aug 22, 2017
c8fadfd
fix some firefox issues
mmalerba Aug 22, 2017
6348841
ignore rounding error in IE
mmalerba Aug 30, 2017
02cd9d3
update new select instance that was added
mmalerba Sep 18, 2017
16b2172
update md-chip-list implementation of MdFormFieldControl
mmalerba Sep 19, 2017
11e7549
fix   issue
mmalerba Sep 21, 2017
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
100 changes: 59 additions & 41 deletions src/demo-app/a11y/select/select-a11y.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,71 +2,89 @@
<h2>Single selection</h2>
<p>Select your favorite color</p>

<md-select placeholder="Colors" [(ngModel)]="selectedColor">
<md-option *ngFor="let color of colors" [value]="color.value">
{{ color.label }}
</md-option>
</md-select>
<md-form-field>
<md-select placeholder="Colors" [(ngModel)]="selectedColor">
<md-option *ngFor="let color of colors" [value]="color.value">
{{ color.label }}
</md-option>
</md-select>
</md-form-field>
</section>

<section>
<h2>Multiple selection</h2>
<p>Pick toppings for your pizza</p>

<md-select placeholder="Toppings" [(ngModel)]="selectedTopping" multiple>
<md-option *ngFor="let topping of toppings" [value]="topping.value">
{{ topping.label }}
</md-option>
</md-select>
<md-form-field>
<md-select placeholder="Toppings" [(ngModel)]="selectedTopping" multiple>
<md-option *ngFor="let topping of toppings" [value]="topping.value">
{{ topping.label }}
</md-option>
</md-select>
</md-form-field>
</section>

<section>
<h2>Grouped options</h2>
<p>Pick your Pokemon</p>

<md-select placeholder="Pokemon" [(ngModel)]="selectedPokemon">
<md-optgroup *ngFor="let group of pokemon" [label]="group.label">
<md-option *ngFor="let creature of group.pokemon" [value]="creature.value">
{{ creature.label }}
</md-option>
</md-optgroup>
</md-select>
<md-form-field>
<md-select placeholder="Pokemon" [(ngModel)]="selectedPokemon">
<md-optgroup *ngFor="let group of pokemon" [label]="group.label">
<md-option *ngFor="let creature of group.pokemon" [value]="creature.value">
{{ creature.label }}
</md-option>
</md-optgroup>
</md-select>
</md-form-field>
</section>

<section>
<h2>Colors</h2>

<div class="select-a11y-spacer">
<md-select placeholder="ZIP code" color="primary">
<md-option value="2000">2000</md-option>
<md-option value="2100">2100</md-option>
</md-select>
<md-form-field color="primary">
<md-select placeholder="ZIP code">
<md-option value="2000">2000</md-option>
<md-option value="2100">2100</md-option>
</md-select>
</md-form-field>

<md-select placeholder="State" color="accent">
<md-option value="alaska">Alaska</md-option>
<md-option value="alabama">Alabama</md-option>
</md-select>
<md-form-field color="accent">
<md-select placeholder="State">
<md-option value="alaska">Alaska</md-option>
<md-option value="alabama">Alabama</md-option>
</md-select>
</md-form-field>

<md-select placeholder="Language" color="warn">
<md-option value="english">English</md-option>
<md-option value="spanish">Spanish</md-option>
</md-select>
<md-form-field color="warn">
<md-select placeholder="Language">
<md-option value="english">English</md-option>
<md-option value="spanish">Spanish</md-option>
</md-select>
</md-form-field>
</div>

<div class="select-a11y-spacer">
<md-select placeholder="Digimon" color="primary" multiple>
<md-option value="mihiramon">Mihiramon</md-option>
<md-option value="sandiramon">Sandiramon</md-option>
</md-select>
<md-form-field color="primary">
<md-select placeholder="Digimon" multiple>
<md-option value="mihiramon">Mihiramon</md-option>
<md-option value="sandiramon">Sandiramon</md-option>
</md-select>
</md-form-field>

<md-select placeholder="Drink" color="accent" multiple>
<md-option value="water">Water</md-option>
<md-option value="coke">Coke</md-option>
</md-select>
<md-form-field color="accent">
<md-select placeholder="Drink" multiple>
<md-option value="water">Water</md-option>
<md-option value="coke">Coke</md-option>
</md-select>
</md-form-field>

<md-select placeholder="Theme" color="warn" multiple>
<md-option value="light">Light</md-option>
<md-option value="dark">Dark</md-option>
</md-select>
<md-form-field color="warn">
<md-select placeholder="Theme" multiple>
<md-option value="light">Light</md-option>
<md-option value="dark">Dark</md-option>
</md-select>
</md-form-field>
</div>
</section>
18 changes: 12 additions & 6 deletions src/demo-app/baseline/baseline-demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@
<input mdInput placeholder="Input" value="Text Input">
</md-form-field>
| Text 5 |
<md-select placeholder="Select">
<md-option value="option">Option</md-option>
</md-select>
<md-form-field>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

API-wise, do we really want people to have to wrap every select in a form field? E.g. if you were using option groups, you'd have to write 4 levels of HTML. Aside from having to proxy a few @Input-s, what are the cons of having the form field be consumed by md-select internally?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the past we've preferred composition style APIs since they're more flexible, even if they are a bit more verbose. I think the extra typing is worth it, but it's a fair point. @jelbourn do you have an opinion?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do like the consistency of having both select and input inside the same form-field; it makes it clear that the prefix, suffix, hint, and error belong to the form field. Very explicit, no magic. It's also more maintainable for us, since we don't have to forward along every form-field API through select over time.

I don't feel incredibly strongly about it, though. @mmalerba up to you if you think it would be the same amount of work to do it the other way around; it would certainly make the migration easier

<md-select placeholder="This placeholder is really really really long">
<md-option value="option">Option</md-option>
<md-option value="long">This option is really really really long</md-option>
</md-select>
</md-form-field>
| Text 6 |
<md-form-field>
<textarea mdInput placeholder="Input" mdTextareaAutosize>Textarea&#10;Line 2</textarea>
Expand All @@ -42,9 +45,12 @@ <h1>
<input mdInput placeholder="Input" value="Text Input">
</md-form-field>
| Text 5 |
<md-select placeholder="Select">
<md-option value="option">Option</md-option>
</md-select>
<md-form-field>
<md-select placeholder="This placeholder is really really really long">
<md-option value="option">Option</md-option>
<md-option value="long">This option is really really really long</md-option>
</md-select>
</md-form-field>
| Text 6 |
<md-form-field>
<textarea mdInput placeholder="Input" mdTextareaAutosize>Textarea&#10;Line 2</textarea>
Expand Down
12 changes: 7 additions & 5 deletions src/demo-app/dialog/dialog-demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,13 @@ <h2>Dialog backdrop</h2>
<h2>Other options</h2>

<p>
<md-select placeholder="Button alignment" [(ngModel)]="actionsAlignment">
<md-option>Start</md-option>
<md-option value="end">End</md-option>
<md-option value="center">Center</md-option>
</md-select>
<md-form-field>
<md-select placeholder="Button alignment" [(ngModel)]="actionsAlignment">
<md-option>Start</md-option>
<md-option value="end">End</md-option>
<md-option value="center">Center</md-option>
</md-select>
</md-form-field>
</p>

<p>
Expand Down
105 changes: 62 additions & 43 deletions src/demo-app/select/select-demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,18 @@
<md-card>
<md-card-subtitle>ngModel</md-card-subtitle>

<md-select placeholder="Drink" [color]="drinksTheme" [(ngModel)]="currentDrink" [required]="drinksRequired"
[disabled]="drinksDisabled" [floatPlaceholder]="floatPlaceholder" #drinkControl="ngModel">
<md-option>None</md-option>
<md-option *ngFor="let drink of drinks" [value]="drink.value" [disabled]="drink.disabled">
{{ drink.viewValue }}
</md-option>
</md-select>
<md-form-field [floatPlaceholder]="floatPlaceholder" [color]="drinksTheme">
<md-select placeholder="Drink" [(ngModel)]="currentDrink" [required]="drinksRequired"
[disabled]="drinksDisabled" #drinkControl="ngModel">
<md-option>None</md-option>
<md-option *ngFor="let drink of drinks" [value]="drink.value" [disabled]="drink.disabled">
{{ drink.viewValue }}
</md-option>
</md-select>
<md-icon mdPrefix class="demo-drink-icon">local_drink</md-icon>
<md-hint>Pick a drink!</md-hint>
<md-error>You must make a selection</md-error>
</md-form-field>
<p> Value: {{ currentDrink }} </p>
<p> Touched: {{ drinkControl.touched }} </p>
<p> Dirty: {{ drinkControl.dirty }} </p>
Expand All @@ -28,7 +33,9 @@
<p>
<label for="drinks-theme">Theme:</label>
<select [(ngModel)]="drinksTheme" id="drinks-theme">
<option *ngFor="let theme of availableThemes" [value]="theme.value">{{ theme.name }}</option>
<option *ngFor="let theme of availableThemes" [value]="theme.value">
{{theme.name}}
</option>
</select>
</p>

Expand All @@ -42,12 +49,14 @@
<md-card-subtitle>Multiple selection</md-card-subtitle>

<md-card-content>
<md-select multiple [color]="pokemonTheme" placeholder="Pokemon" [(ngModel)]="currentPokemon"
[required]="pokemonRequired" [disabled]="pokemonDisabled" #pokemonControl="ngModel">
<md-option *ngFor="let creature of pokemon" [value]="creature.value">
{{ creature.viewValue }}
</md-option>
</md-select>
<md-form-field [color]="pokemonTheme">
<md-select multiple placeholder="Pokemon" [(ngModel)]="currentPokemon"
[required]="pokemonRequired" [disabled]="pokemonDisabled" #pokemonControl="ngModel">
<md-option *ngFor="let creature of pokemon" [value]="creature.value">
{{ creature.viewValue }}
</md-option>
</md-select>
</md-form-field>
<p> Value: {{ currentPokemon }} </p>
<p> Touched: {{ pokemonControl.touched }} </p>
<p> Dirty: {{ pokemonControl.dirty }} </p>
Expand All @@ -68,12 +77,14 @@
<md-card>
<md-card-subtitle>Without Angular forms</md-card-subtitle>

<md-select placeholder="Digimon" [(value)]="currentDigimon">
<md-option>None</md-option>
<md-option *ngFor="let creature of digimon" [value]="creature.value">
{{ creature.viewValue }}
</md-option>
</md-select>
<md-form-field>
<md-select placeholder="Digimon" [(value)]="currentDigimon">
<md-option>None</md-option>
<md-option *ngFor="let creature of digimon" [value]="creature.value">
{{ creature.viewValue }}
</md-option>
</md-select>
</md-form-field>

<p>Value: {{ currentDigimon }}</p>

Expand All @@ -85,30 +96,34 @@
<md-card-subtitle>Option groups</md-card-subtitle>

<md-card-content>
<md-select placeholder="Pokemon" [(ngModel)]="currentPokemonFromGroup">
<md-optgroup *ngFor="let group of pokemonGroups" [label]="group.name"
[disabled]="group.disabled">
<md-option *ngFor="let creature of group.pokemon" [value]="creature.value">
{{ creature.viewValue }}
</md-option>
</md-optgroup>
</md-select>
<md-form-field>
<md-select placeholder="Pokemon" [(ngModel)]="currentPokemonFromGroup">
<md-optgroup *ngFor="let group of pokemonGroups" [label]="group.name"
[disabled]="group.disabled">
<md-option *ngFor="let creature of group.pokemon" [value]="creature.value">
{{ creature.viewValue }}
</md-option>
</md-optgroup>
</md-select>
</md-form-field>
</md-card-content>
</md-card>


<md-card>
<md-card-subtitle>compareWith</md-card-subtitle>
<md-card-content>
<md-select placeholder="Drink" [color]="drinksTheme"
[(ngModel)]="currentDrinkObject"
[required]="drinkObjectRequired"
[compareWith]="compareByValue ? compareDrinkObjectsByValue : compareByReference"
#drinkObjectControl="ngModel">
<md-option *ngFor="let drink of drinks" [value]="drink" [disabled]="drink.disabled">
{{ drink.viewValue }}
</md-option>
</md-select>
<md-form-field [color]="drinksTheme">
<md-select placeholder="Drink"
[(ngModel)]="currentDrinkObject"
[required]="drinkObjectRequired"
[compareWith]="compareByValue ? compareDrinkObjectsByValue : compareByReference"
#drinkObjectControl="ngModel">
<md-option *ngFor="let drink of drinks" [value]="drink" [disabled]="drink.disabled">
{{ drink.viewValue }}
</md-option>
</md-select>
</md-form-field>
<p> Value: {{ currentDrinkObject | json }} </p>
<p> Touched: {{ drinkObjectControl.touched }} </p>
<p> Dirty: {{ drinkObjectControl.dirty }} </p>
Expand All @@ -130,9 +145,11 @@
<md-card-subtitle>formControl</md-card-subtitle>

<md-card-content>
<md-select placeholder="Food i would like to eat" [formControl]="foodControl">
<md-option *ngFor="let food of foods" [value]="food.value"> {{ food.viewValue }}</md-option>
</md-select>
<md-form-field>
<md-select placeholder="Food i would like to eat" [formControl]="foodControl">
<md-option *ngFor="let food of foods" [value]="food.value"> {{ food.viewValue }}</md-option>
</md-select>
</md-form-field>
<p> Value: {{ foodControl.value }} </p>
<p> Touched: {{ foodControl.touched }} </p>
<p> Dirty: {{ foodControl.dirty }} </p>
Expand All @@ -149,9 +166,11 @@
<md-card-subtitle>Change event</md-card-subtitle>

<md-card-content>
<md-select placeholder="Starter Pokemon" (change)="latestChangeEvent = $event">
<md-option *ngFor="let creature of pokemon" [value]="creature.value">{{ creature.viewValue }}</md-option>
</md-select>
<md-form-field>
<md-select placeholder="Starter Pokemon" (change)="latestChangeEvent = $event">
<md-option *ngFor="let creature of pokemon" [value]="creature.value">{{ creature.viewValue }}</md-option>
</md-select>
</md-form-field>

<p> Change event value: {{ latestChangeEvent?.value }} </p>
</md-card-content>
Expand Down
4 changes: 4 additions & 0 deletions src/demo-app/select/select-demo.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,8 @@
margin: 24px;
}

.demo-drink-icon {
vertical-align: bottom;
padding-right: 0.25em;
}
}
26 changes: 15 additions & 11 deletions src/demo-app/snack-bar/snack-bar-demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,21 @@ <h1>SnackBar demo</h1>
</div>
<div>
<div>Position in page: </div>
<md-select [(ngModel)]="horizontalPosition">
<md-option value="start">Start</md-option>
<md-option value="end">End</md-option>
<md-option value="left">Left</md-option>
<md-option value="right">Right</md-option>
<md-option value="center">Center</md-option>
</md-select>
<md-select [(ngModel)]="verticalPosition">
<md-option value="top">Top</md-option>
<md-option value="bottom">Bottom</md-option>
</md-select>
<md-form-field>
<md-select [(ngModel)]="horizontalPosition">
<md-option value="start">Start</md-option>
<md-option value="end">End</md-option>
<md-option value="left">Left</md-option>
<md-option value="right">Right</md-option>
<md-option value="center">Center</md-option>
</md-select>
</md-form-field>
<md-form-field>
<md-select [(ngModel)]="verticalPosition">
<md-option value="top">Top</md-option>
<md-option value="bottom">Bottom</md-option>
</md-select>
</md-form-field>
</div>
<div>
<md-checkbox [(ngModel)]="action">
Expand Down
Loading