Skip to content

Commit b711c2b

Browse files
committed
feat(MdInput): README.md improvements and autofill support.
* Change the CSS to allow for autofill reactions; it works! * Add a lot of examples and information to the README.md * Add support for `warn` color to the labels.
1 parent 5a6657a commit b711c2b

File tree

7 files changed

+239
-42
lines changed

7 files changed

+239
-42
lines changed

src/components/input/README.md

Lines changed: 83 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22

33
Inputs are the basic input component of Material 2. The spec can be found [here](https://www.google.com/design/spec/components/text-fields.html).
44

5-
### Screenshots
5+
6+
7+
## Notes
8+
* The `<md-input>` component fully support two-way binding of `ngModel`, as if it was a normal `<input>`.
69

710

811

@@ -12,22 +15,27 @@ At the time of writing this README, the `[type]` attribute is copied to the actu
1215

1316
The valid `type` attribute values are any supported by your browser, with the exception of `file`, `checkbox` and `radio`. File inputs aren't supported for now, while check boxes and radio buttons have their own components.
1417

18+
19+
1520
## Prefix and Suffix
1621

1722
You can include HTML before, and after the input tag, as prefix or suffix. It will be underlined as per the Material specification, and clicking it will focus the input.
1823

1924
To add a prefix, use the `md-prefix` attribute on the element. Similarly, to add a suffix, use the `md-suffix` attribute. For example, in a template:
2025

26+
#### Example
27+
2128
```html
22-
<md-input type="number" placeholder="amount">
23-
<span md-prefix>$</span>
29+
<md-input placeholder="amount" align="end">
30+
<span md-prefix>$&nbsp;</span>
2431
<span md-suffix>.00</span>
2532
</md-input>
2633
```
2734

2835
Will result in this:
2936

30-
!!!! INSERT SCREENSHOT HERE.
37+
<img src="https://material.angularjs.org/material2_assets/input/prefix-suffix.png">
38+
3139

3240

3341
## Hint Labels
@@ -38,5 +46,76 @@ You specify a hint-label in one of two ways; either using the `hintLabel` attrib
3846

3947
Specifying a side twice will result in an exception during initialization.
4048

49+
#### Example
50+
51+
A simple character counter can be made like the following:
52+
53+
```html
54+
<md-input placeholder="Character count (100 max)" maxLength="100" class="demo-full-width"
55+
value="Hello world. How are you?"
56+
#characterCountHintExample>
57+
<md-hint align="end">{{characterCountHintExample.characterCount}} / 100</md-hint>
58+
</md-input>
59+
```
60+
61+
<img src="https://material.angularjs.org/material2_assets/input/character-count.png">
62+
63+
64+
4165
## Divider Color
4266

67+
The divider (line under the <md-input> content) color can be changed by using the `dividerColor` attribute. A value of `primary` is the default and will correspond to your theme primary color. Alternatively, you can specify `accent` or `warn`.
68+
69+
#### Example
70+
71+
^((please not that this example has been doctored to show the colors; they would normally show only on focus)^)
72+
73+
<img src="https://material.angularjs.org/material2_assets/input/divider-colors.png">
74+
75+
76+
77+
## Labelling
78+
79+
You can label the `<md-input>` as you would a regular `<input>`.
80+
81+
82+
83+
## Full Forms
84+
85+
You can make a full form using inputs, and it will support autofill natively.
86+
87+
#### Example
88+
89+
```html
90+
<md-card class="demo-card demo-basic">
91+
<md-toolbar color="primary">Basic</md-toolbar>
92+
<md-card-content>
93+
<form>
94+
<md-input class="demo-full-width" placeholder="Company (disabled)" disabled value="Google">
95+
</md-input>
96+
97+
<table style="width: 100%" cellspacing="0"><tr>
98+
<td><md-input placeholder="First name" style="width: 100%"></md-input></td>
99+
<td><md-input placeholder="Long Last Name That Will Be Truncated" style="width: 100%"></md-input></td>
100+
</tr></table>
101+
<p>
102+
<md-input class="demo-full-width" placeholder="Address" value="1600 Amphitheatre Pkway"></md-input>
103+
<md-input class="demo-full-width" placeholder="Address 2"></md-input>
104+
</p>
105+
<table style="width: 100%" cellspacing="0"><tr>
106+
<td><md-input class="demo-full-width" placeholder="City"></md-input></td>
107+
<td><md-input class="demo-full-width" placeholder="State"></md-input></td>
108+
<td><md-input #postalCode class="demo-full-width" maxLength="5"
109+
placeholder="Postal Code"
110+
value="94043">
111+
<md-hint align="end">{{postalCode.characterCount}} / 5</md-hint>
112+
</md-input></td>
113+
</tr></table>
114+
</form>
115+
</md-card-content>
116+
</md-card>
117+
```
118+
119+
Will result in this:
120+
121+
<img src="https://material.angularjs.org/material2_assets/input/full-form.png">

src/components/input/input.html

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,38 @@
22
<div class="md-input-table">
33
<div class="md-input-prefix"><ng-content select="[md-prefix]"></ng-content></div>
44

5-
<label class="md-input-placeholder"
6-
[attr.for]="id"
7-
[class.md-empty]="empty"
8-
[class.md-focused]="focused"
9-
[class.md-float]="floatingPlaceholder"
10-
[class.md-accent]="dividerColor == 'accent'"
11-
*ngIf="hasPlaceholder()">
12-
<ng-content select="md-placeholder"></ng-content>
13-
{{placeholder}}
14-
<span class="md-placeholder-required" *ngIf="required">*</span>
15-
</label>
5+
<div class="md-input-infix">
6+
<input #input
7+
aria-target
8+
class="md-input-element"
9+
[class.md-end]="align == 'end'"
10+
[attr.aria-label]="ariaLabel"
11+
[attr.aria-labelledby]="ariaLabelledBy"
12+
[attr.aria-disabled]="ariaDisabled"
13+
[attr.aria-required]="ariaRequired"
14+
[attr.aria-invalid]="ariaInvalid"
15+
[id]="id"
16+
[disabled]="disabled"
17+
[required]="required"
18+
[attr.maxlength]="maxLength"
19+
[type]="type"
20+
(focus)="onFocus()"
21+
(blur)="onBlur()"
22+
[(ngModel)]="value">
1623

17-
<input #input
18-
aria-target
19-
class="md-input-element"
20-
[class.md-end]="align == 'end'"
21-
[attr.aria-label]="ariaLabel"
22-
[attr.aria-labelledby]="ariaLabelledBy"
23-
[attr.aria-disabled]="ariaDisabled"
24-
[attr.aria-required]="ariaRequired"
25-
[attr.aria-invalid]="ariaInvalid"
26-
[id]="id"
27-
[disabled]="disabled"
28-
[required]="required"
29-
[attr.maxlength]="maxLength"
30-
[type]="type"
31-
(focus)="onFocus()"
32-
(blur)="onBlur()"
33-
[(ngModel)]="value">
24+
<label class="md-input-placeholder"
25+
[attr.for]="id"
26+
[class.md-empty]="empty"
27+
[class.md-focused]="focused"
28+
[class.md-float]="floatingPlaceholder"
29+
[class.md-accent]="dividerColor == 'accent'"
30+
[class.md-warn]="dividerColor == 'warn'"
31+
*ngIf="hasPlaceholder()">
32+
<ng-content select="md-placeholder"></ng-content>
33+
{{placeholder}}
34+
<span class="md-placeholder-required" *ngIf="required">*</span>
35+
</label>
36+
</div>
3437

3538
<div class="md-input-suffix"><ng-content select="[md-suffix]"></ng-content></div>
3639
</div>
@@ -39,7 +42,8 @@
3942
[class.md-disabled]="disabled">
4043
<span class="md-input-ripple"
4144
[class.md-focused]="focused"
42-
[class.md-accent]="dividerColor == 'accent'"></span>
45+
[class.md-accent]="dividerColor == 'accent'"
46+
[class.md-warn]="dividerColor == 'warn'"></span>
4347
</div>
4448

4549
<div *ngIf="hintLabel != ''" class="md-hint">{{hintLabel}}</div>

src/components/input/input.scss

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,37 @@ $md-input-required-placeholder-color: md-color($md-accent);
1111
// Underline colors.
1212
$md-input-underline-color: md-color($md-foreground, hint-text);
1313
$md-input-underline-color-accent: md-color($md-accent);
14+
$md-input-underline-color-warn: md-color($md-warn);
1415
$md-input-underline-disabled-color: md-color($md-foreground, hint-text);
1516
$md-input-underline-focused-color: md-color($md-primary);
1617

1718
// Gradient for showing the dashed line when the input is disabled.
1819
$md-input-underline-disabled-background-image: linear-gradient(to right,
1920
rgba(0,0,0,0.26) 0%, rgba(0,0,0,0.26) 33%, transparent 0%);
2021

22+
23+
/**
24+
* Applies a floating placeholder above the input itself.
25+
*/
26+
%md-input-placeholder-floating {
27+
visibility: visible;
28+
padding-bottom: 5px;
29+
transform: translateY(-100%) scale(0.75);
30+
31+
.md-placeholder-required {
32+
color: $md-input-required-placeholder-color;
33+
}
34+
}
35+
36+
2137
:host {
2238
display: inline-block;
2339
position: relative;
2440
font-family: $md-font-family;
2541

42+
// To avoid problems with text-align.
43+
text-align: left;
44+
2645
// Global wrapper. We need to apply margin to the element for spacing, but
2746
// cannot apply it to the host element directly.
2847
.md-input-wrapper {
@@ -61,18 +80,32 @@ $md-input-underline-disabled-background-image: linear-gradient(to right,
6180
}
6281
}
6382

83+
.md-input-infix {
84+
position: relative;
85+
}
86+
6487
// The placeholder label. This is invisible unless it is. The logic to show it is
6588
// basically `empty || (float && (!empty || focused))`. Float is dependent on the
6689
// `floatingPlaceholder` input.
6790
.md-input-placeholder {
91+
// The placeholder is after the <input>, but needs to be aligned top-left of the
92+
// infix <div>.
6893
position: absolute;
94+
left: 0;
95+
top: 0;
96+
6997
visibility: hidden;
7098
font-size: 100%;
7199
pointer-events: none; // We shouldn't catch mouse events (let them through).
72100
color: $md-input-placeholder-color;
73101
z-index: 1;
74102

103+
// Put ellipsis text overflow.
75104
width: 100%;
105+
display: block;
106+
white-space: nowrap;
107+
text-overflow: ellipsis;
108+
overflow-x: hidden;
76109

77110
transform: translateY(0);
78111
transform-origin: bottom left;
@@ -87,13 +120,7 @@ $md-input-underline-disabled-background-image: linear-gradient(to right,
87120

88121
// Show the placeholder above the input when it's not empty, or focused.
89122
&.md-float:not(.md-empty), &.md-float.md-focused {
90-
visibility: visible;
91-
padding-bottom: 5px;
92-
transform: translateY(-100%) scale(0.75);
93-
94-
.md-placeholder-required {
95-
color: $md-input-required-placeholder-color;
96-
}
123+
@extend %md-input-placeholder-floating;
97124
}
98125

99126
// :focus is applied to the input, but we apply md-focused to the other elements
@@ -104,9 +131,21 @@ $md-input-underline-disabled-background-image: linear-gradient(to right,
104131
&.md-accent {
105132
color: $md-input-underline-color-accent;
106133
}
134+
&.md-warn {
135+
color: $md-input-underline-color-warn;
136+
}
107137
}
108138
}
109139

140+
// Pseudo-class for Chrome and Safari auto-fill to move the placeholder to
141+
// the floating position. This is necessary because these browsers do not actually
142+
// fire any events when a form auto-fill is occurring.
143+
// Once the autofill is committed, a change event happen and the regular md-input
144+
// classes take over to fulfill this behaviour.
145+
input:-webkit-autofill + .md-input-placeholder {
146+
@extend %md-input-placeholder-floating;
147+
}
148+
110149
// The underline is what's shown under the input, its prefix and its suffix.
111150
// The ripple is the blue animation coming on top of it.
112151
.md-input-underline {
@@ -140,6 +179,9 @@ $md-input-underline-disabled-background-image: linear-gradient(to right,
140179
&.md-accent {
141180
background-color: $md-input-underline-color-accent;
142181
}
182+
&.md-warn {
183+
background-color: $md-input-underline-color-warn;
184+
}
143185

144186
&.md-focused {
145187
opacity: 1;
@@ -164,6 +206,8 @@ $md-input-underline-disabled-background-image: linear-gradient(to right,
164206

165207
// RTL support.
166208
:host-context([dir="rtl"]) {
209+
text-align: right;
210+
167211
.md-input-placeholder {
168212
transform-origin: bottom right;
169213
}

src/components/input/input.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ export class MdInput implements ControlValueAccessor, AfterContentInit, OnChange
131131
*/
132132
@Input() @OneOf(['start', 'end']) align: string = 'start';
133133
@Input() @BooleanFieldValue() disabled: boolean = false;
134-
@Input() @OneOf(['primary', 'accent']) dividerColor: string = 'primary';
134+
@Input() @OneOf(['primary', 'accent', 'warn']) dividerColor: string = 'primary';
135135
@Input() @BooleanFieldValue() floatingPlaceholder: boolean = true;
136136
@Input() hintLabel: string = '';
137137
@Input() id: string = `md-input-${nextUniqueId++}`;

src/demo-app/input/input-demo.html

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,63 @@
1+
<md-card class="demo-card demo-basic">
2+
<md-toolbar color="primary">Basic</md-toolbar>
3+
<md-card-content>
4+
<form>
5+
<md-input class="demo-full-width" placeholder="Company (disabled)" disabled value="Google">
6+
</md-input>
7+
8+
<table style="width: 100%" cellspacing="0"><tr>
9+
<td><md-input placeholder="First name" style="width: 100%"></md-input></td>
10+
<td><md-input placeholder="Long Last Name That Will Be Truncated" style="width: 100%"></md-input></td>
11+
</tr></table>
12+
<p>
13+
<md-input class="demo-full-width" placeholder="Address" value="1600 Amphitheatre Pkway"></md-input>
14+
<md-input class="demo-full-width" placeholder="Address 2"></md-input>
15+
</p>
16+
<table style="width: 100%" cellspacing="0"><tr>
17+
<td><md-input class="demo-full-width" placeholder="City" value="Mountain View"></md-input></td>
18+
<td><md-input class="demo-full-width" placeholder="State" maxLength="2" value="CA"></md-input></td>
19+
<td><md-input #postalCode class="demo-full-width" maxLength="5"
20+
placeholder="Postal Code"
21+
value="94043">
22+
<md-hint align="end">{{postalCode.characterCount}} / 5</md-hint>
23+
</md-input></td>
24+
</tr></table>
25+
</form>
26+
</md-card-content>
27+
</md-card>
28+
29+
<md-card class="demo-card demo-basic">
30+
<md-toolbar color="primary">Prefix + Suffix</md-toolbar>
31+
<md-card-content>
32+
<md-input placeholder="amount" align="end">
33+
<span md-prefix>$&nbsp;</span>
34+
<span md-suffix>.00</span>
35+
</md-input>
36+
</md-card-content>
37+
</md-card>
38+
39+
<md-card class="demo-card demo-basic">
40+
<md-toolbar color="primary">Divider Colors</md-toolbar>
41+
<md-card-content>
42+
<md-input dividerColor="primary" placeholder="Default Color" value="example"></md-input>
43+
<md-input dividerColor="accent" placeholder="Accent Color" value="example"></md-input>
44+
<md-input dividerColor="warn" placeholder="Warn Color" value="example"></md-input>
45+
</md-card-content>
46+
</md-card>
47+
48+
<md-card class="demo-card demo-basic">
49+
<md-toolbar color="primary">Hints</md-toolbar>
50+
<md-card-content>
51+
<p>
52+
<md-input placeholder="Character count (100 max)" maxLength="100" class="demo-full-width"
53+
value="Hello world. How are you?"
54+
#characterCountHintExample>
55+
<md-hint align="end">{{characterCountHintExample.characterCount}} / 100</md-hint>
56+
</md-input>
57+
</p>
58+
</md-card-content>
59+
</md-card>
60+
161
<md-card class="demo-card">
262
<md-card-title>
363
Hello <md-input [(ngModel)]="name" type="string" placeholder="First name"></md-input>,

0 commit comments

Comments
 (0)