mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
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.
This commit is contained in:
@@ -2,7 +2,10 @@
|
||||
|
||||
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).
|
||||
|
||||
### Screenshots
|
||||
|
||||
|
||||
## Notes
|
||||
* The `<md-input>` component fully support two-way binding of `ngModel`, as if it was a normal `<input>`.
|
||||
|
||||
|
||||
|
||||
@@ -12,22 +15,27 @@ At the time of writing this README, the `[type]` attribute is copied to the actu
|
||||
|
||||
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.
|
||||
|
||||
|
||||
|
||||
## Prefix and Suffix
|
||||
|
||||
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.
|
||||
|
||||
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:
|
||||
|
||||
#### Example
|
||||
|
||||
```html
|
||||
<md-input type="number" placeholder="amount">
|
||||
<span md-prefix>$</span>
|
||||
<md-input placeholder="amount" align="end">
|
||||
<span md-prefix>$ </span>
|
||||
<span md-suffix>.00</span>
|
||||
</md-input>
|
||||
```
|
||||
|
||||
Will result in this:
|
||||
|
||||
!!!! INSERT SCREENSHOT HERE.
|
||||
<img src="https://material.angularjs.org/material2_assets/input/prefix-suffix.png">
|
||||
|
||||
|
||||
|
||||
## Hint Labels
|
||||
@@ -38,5 +46,76 @@ You specify a hint-label in one of two ways; either using the `hintLabel` attrib
|
||||
|
||||
Specifying a side twice will result in an exception during initialization.
|
||||
|
||||
#### Example
|
||||
|
||||
A simple character counter can be made like the following:
|
||||
|
||||
```html
|
||||
<md-input placeholder="Character count (100 max)" maxLength="100" class="demo-full-width"
|
||||
value="Hello world. How are you?"
|
||||
#characterCountHintExample>
|
||||
<md-hint align="end">{{characterCountHintExample.characterCount}} / 100</md-hint>
|
||||
</md-input>
|
||||
```
|
||||
|
||||
<img src="https://material.angularjs.org/material2_assets/input/character-count.png">
|
||||
|
||||
|
||||
|
||||
## Divider Color
|
||||
|
||||
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`.
|
||||
|
||||
#### Example
|
||||
|
||||
^((please not that this example has been doctored to show the colors; they would normally show only on focus)^)
|
||||
|
||||
<img src="https://material.angularjs.org/material2_assets/input/divider-colors.png">
|
||||
|
||||
|
||||
|
||||
## Labelling
|
||||
|
||||
You can label the `<md-input>` as you would a regular `<input>`.
|
||||
|
||||
|
||||
|
||||
## Full Forms
|
||||
|
||||
You can make a full form using inputs, and it will support autofill natively.
|
||||
|
||||
#### Example
|
||||
|
||||
```html
|
||||
<md-card class="demo-card demo-basic">
|
||||
<md-toolbar color="primary">Basic</md-toolbar>
|
||||
<md-card-content>
|
||||
<form>
|
||||
<md-input class="demo-full-width" placeholder="Company (disabled)" disabled value="Google">
|
||||
</md-input>
|
||||
|
||||
<table style="width: 100%" cellspacing="0"><tr>
|
||||
<td><md-input placeholder="First name" style="width: 100%"></md-input></td>
|
||||
<td><md-input placeholder="Long Last Name That Will Be Truncated" style="width: 100%"></md-input></td>
|
||||
</tr></table>
|
||||
<p>
|
||||
<md-input class="demo-full-width" placeholder="Address" value="1600 Amphitheatre Pkway"></md-input>
|
||||
<md-input class="demo-full-width" placeholder="Address 2"></md-input>
|
||||
</p>
|
||||
<table style="width: 100%" cellspacing="0"><tr>
|
||||
<td><md-input class="demo-full-width" placeholder="City"></md-input></td>
|
||||
<td><md-input class="demo-full-width" placeholder="State"></md-input></td>
|
||||
<td><md-input #postalCode class="demo-full-width" maxLength="5"
|
||||
placeholder="Postal Code"
|
||||
value="94043">
|
||||
<md-hint align="end">{{postalCode.characterCount}} / 5</md-hint>
|
||||
</md-input></td>
|
||||
</tr></table>
|
||||
</form>
|
||||
</md-card-content>
|
||||
</md-card>
|
||||
```
|
||||
|
||||
Will result in this:
|
||||
|
||||
<img src="https://material.angularjs.org/material2_assets/input/full-form.png">
|
||||
|
||||
@@ -2,35 +2,38 @@
|
||||
<div class="md-input-table">
|
||||
<div class="md-input-prefix"><ng-content select="[md-prefix]"></ng-content></div>
|
||||
|
||||
<label class="md-input-placeholder"
|
||||
[attr.for]="id"
|
||||
[class.md-empty]="empty"
|
||||
[class.md-focused]="focused"
|
||||
[class.md-float]="floatingPlaceholder"
|
||||
[class.md-accent]="dividerColor == 'accent'"
|
||||
*ngIf="hasPlaceholder()">
|
||||
<ng-content select="md-placeholder"></ng-content>
|
||||
{{placeholder}}
|
||||
<span class="md-placeholder-required" *ngIf="required">*</span>
|
||||
</label>
|
||||
<div class="md-input-infix">
|
||||
<input #input
|
||||
aria-target
|
||||
class="md-input-element"
|
||||
[class.md-end]="align == 'end'"
|
||||
[attr.aria-label]="ariaLabel"
|
||||
[attr.aria-labelledby]="ariaLabelledBy"
|
||||
[attr.aria-disabled]="ariaDisabled"
|
||||
[attr.aria-required]="ariaRequired"
|
||||
[attr.aria-invalid]="ariaInvalid"
|
||||
[id]="id"
|
||||
[disabled]="disabled"
|
||||
[required]="required"
|
||||
[attr.maxlength]="maxLength"
|
||||
[type]="type"
|
||||
(focus)="onFocus()"
|
||||
(blur)="onBlur()"
|
||||
[(ngModel)]="value">
|
||||
|
||||
<input #input
|
||||
aria-target
|
||||
class="md-input-element"
|
||||
[class.md-end]="align == 'end'"
|
||||
[attr.aria-label]="ariaLabel"
|
||||
[attr.aria-labelledby]="ariaLabelledBy"
|
||||
[attr.aria-disabled]="ariaDisabled"
|
||||
[attr.aria-required]="ariaRequired"
|
||||
[attr.aria-invalid]="ariaInvalid"
|
||||
[id]="id"
|
||||
[disabled]="disabled"
|
||||
[required]="required"
|
||||
[attr.maxlength]="maxLength"
|
||||
[type]="type"
|
||||
(focus)="onFocus()"
|
||||
(blur)="onBlur()"
|
||||
[(ngModel)]="value">
|
||||
<label class="md-input-placeholder"
|
||||
[attr.for]="id"
|
||||
[class.md-empty]="empty"
|
||||
[class.md-focused]="focused"
|
||||
[class.md-float]="floatingPlaceholder"
|
||||
[class.md-accent]="dividerColor == 'accent'"
|
||||
[class.md-warn]="dividerColor == 'warn'"
|
||||
*ngIf="hasPlaceholder()">
|
||||
<ng-content select="md-placeholder"></ng-content>
|
||||
{{placeholder}}
|
||||
<span class="md-placeholder-required" *ngIf="required">*</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="md-input-suffix"><ng-content select="[md-suffix]"></ng-content></div>
|
||||
</div>
|
||||
@@ -39,7 +42,8 @@
|
||||
[class.md-disabled]="disabled">
|
||||
<span class="md-input-ripple"
|
||||
[class.md-focused]="focused"
|
||||
[class.md-accent]="dividerColor == 'accent'"></span>
|
||||
[class.md-accent]="dividerColor == 'accent'"
|
||||
[class.md-warn]="dividerColor == 'warn'"></span>
|
||||
</div>
|
||||
|
||||
<div *ngIf="hintLabel != ''" class="md-hint">{{hintLabel}}</div>
|
||||
|
||||
@@ -11,6 +11,7 @@ $md-input-required-placeholder-color: md-color($md-accent);
|
||||
// Underline colors.
|
||||
$md-input-underline-color: md-color($md-foreground, hint-text);
|
||||
$md-input-underline-color-accent: md-color($md-accent);
|
||||
$md-input-underline-color-warn: md-color($md-warn);
|
||||
$md-input-underline-disabled-color: md-color($md-foreground, hint-text);
|
||||
$md-input-underline-focused-color: md-color($md-primary);
|
||||
|
||||
@@ -18,11 +19,29 @@ $md-input-underline-focused-color: md-color($md-primary);
|
||||
$md-input-underline-disabled-background-image: linear-gradient(to right,
|
||||
rgba(0,0,0,0.26) 0%, rgba(0,0,0,0.26) 33%, transparent 0%);
|
||||
|
||||
|
||||
/**
|
||||
* Applies a floating placeholder above the input itself.
|
||||
*/
|
||||
%md-input-placeholder-floating {
|
||||
visibility: visible;
|
||||
padding-bottom: 5px;
|
||||
transform: translateY(-100%) scale(0.75);
|
||||
|
||||
.md-placeholder-required {
|
||||
color: $md-input-required-placeholder-color;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
:host {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
font-family: $md-font-family;
|
||||
|
||||
// To avoid problems with text-align.
|
||||
text-align: left;
|
||||
|
||||
// Global wrapper. We need to apply margin to the element for spacing, but
|
||||
// cannot apply it to the host element directly.
|
||||
.md-input-wrapper {
|
||||
@@ -61,18 +80,32 @@ $md-input-underline-disabled-background-image: linear-gradient(to right,
|
||||
}
|
||||
}
|
||||
|
||||
.md-input-infix {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
// The placeholder label. This is invisible unless it is. The logic to show it is
|
||||
// basically `empty || (float && (!empty || focused))`. Float is dependent on the
|
||||
// `floatingPlaceholder` input.
|
||||
.md-input-placeholder {
|
||||
// The placeholder is after the <input>, but needs to be aligned top-left of the
|
||||
// infix <div>.
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
|
||||
visibility: hidden;
|
||||
font-size: 100%;
|
||||
pointer-events: none; // We shouldn't catch mouse events (let them through).
|
||||
color: $md-input-placeholder-color;
|
||||
z-index: 1;
|
||||
|
||||
// Put ellipsis text overflow.
|
||||
width: 100%;
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow-x: hidden;
|
||||
|
||||
transform: translateY(0);
|
||||
transform-origin: bottom left;
|
||||
@@ -87,13 +120,7 @@ $md-input-underline-disabled-background-image: linear-gradient(to right,
|
||||
|
||||
// Show the placeholder above the input when it's not empty, or focused.
|
||||
&.md-float:not(.md-empty), &.md-float.md-focused {
|
||||
visibility: visible;
|
||||
padding-bottom: 5px;
|
||||
transform: translateY(-100%) scale(0.75);
|
||||
|
||||
.md-placeholder-required {
|
||||
color: $md-input-required-placeholder-color;
|
||||
}
|
||||
@extend %md-input-placeholder-floating;
|
||||
}
|
||||
|
||||
// :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,
|
||||
&.md-accent {
|
||||
color: $md-input-underline-color-accent;
|
||||
}
|
||||
&.md-warn {
|
||||
color: $md-input-underline-color-warn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pseudo-class for Chrome and Safari auto-fill to move the placeholder to
|
||||
// the floating position. This is necessary because these browsers do not actually
|
||||
// fire any events when a form auto-fill is occurring.
|
||||
// Once the autofill is committed, a change event happen and the regular md-input
|
||||
// classes take over to fulfill this behaviour.
|
||||
input:-webkit-autofill + .md-input-placeholder {
|
||||
@extend %md-input-placeholder-floating;
|
||||
}
|
||||
|
||||
// The underline is what's shown under the input, its prefix and its suffix.
|
||||
// The ripple is the blue animation coming on top of it.
|
||||
.md-input-underline {
|
||||
@@ -140,6 +179,9 @@ $md-input-underline-disabled-background-image: linear-gradient(to right,
|
||||
&.md-accent {
|
||||
background-color: $md-input-underline-color-accent;
|
||||
}
|
||||
&.md-warn {
|
||||
background-color: $md-input-underline-color-warn;
|
||||
}
|
||||
|
||||
&.md-focused {
|
||||
opacity: 1;
|
||||
@@ -164,6 +206,8 @@ $md-input-underline-disabled-background-image: linear-gradient(to right,
|
||||
|
||||
// RTL support.
|
||||
:host-context([dir="rtl"]) {
|
||||
text-align: right;
|
||||
|
||||
.md-input-placeholder {
|
||||
transform-origin: bottom right;
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ export class MdInput implements ControlValueAccessor, AfterContentInit, OnChange
|
||||
*/
|
||||
@Input() @OneOf(['start', 'end']) align: string = 'start';
|
||||
@Input() @BooleanFieldValue() disabled: boolean = false;
|
||||
@Input() @OneOf(['primary', 'accent']) dividerColor: string = 'primary';
|
||||
@Input() @OneOf(['primary', 'accent', 'warn']) dividerColor: string = 'primary';
|
||||
@Input() @BooleanFieldValue() floatingPlaceholder: boolean = true;
|
||||
@Input() hintLabel: string = '';
|
||||
@Input() id: string = `md-input-${nextUniqueId++}`;
|
||||
|
||||
@@ -1,3 +1,63 @@
|
||||
<md-card class="demo-card demo-basic">
|
||||
<md-toolbar color="primary">Basic</md-toolbar>
|
||||
<md-card-content>
|
||||
<form>
|
||||
<md-input class="demo-full-width" placeholder="Company (disabled)" disabled value="Google">
|
||||
</md-input>
|
||||
|
||||
<table style="width: 100%" cellspacing="0"><tr>
|
||||
<td><md-input placeholder="First name" style="width: 100%"></md-input></td>
|
||||
<td><md-input placeholder="Long Last Name That Will Be Truncated" style="width: 100%"></md-input></td>
|
||||
</tr></table>
|
||||
<p>
|
||||
<md-input class="demo-full-width" placeholder="Address" value="1600 Amphitheatre Pkway"></md-input>
|
||||
<md-input class="demo-full-width" placeholder="Address 2"></md-input>
|
||||
</p>
|
||||
<table style="width: 100%" cellspacing="0"><tr>
|
||||
<td><md-input class="demo-full-width" placeholder="City" value="Mountain View"></md-input></td>
|
||||
<td><md-input class="demo-full-width" placeholder="State" maxLength="2" value="CA"></md-input></td>
|
||||
<td><md-input #postalCode class="demo-full-width" maxLength="5"
|
||||
placeholder="Postal Code"
|
||||
value="94043">
|
||||
<md-hint align="end">{{postalCode.characterCount}} / 5</md-hint>
|
||||
</md-input></td>
|
||||
</tr></table>
|
||||
</form>
|
||||
</md-card-content>
|
||||
</md-card>
|
||||
|
||||
<md-card class="demo-card demo-basic">
|
||||
<md-toolbar color="primary">Prefix + Suffix</md-toolbar>
|
||||
<md-card-content>
|
||||
<md-input placeholder="amount" align="end">
|
||||
<span md-prefix>$ </span>
|
||||
<span md-suffix>.00</span>
|
||||
</md-input>
|
||||
</md-card-content>
|
||||
</md-card>
|
||||
|
||||
<md-card class="demo-card demo-basic">
|
||||
<md-toolbar color="primary">Divider Colors</md-toolbar>
|
||||
<md-card-content>
|
||||
<md-input dividerColor="primary" placeholder="Default Color" value="example"></md-input>
|
||||
<md-input dividerColor="accent" placeholder="Accent Color" value="example"></md-input>
|
||||
<md-input dividerColor="warn" placeholder="Warn Color" value="example"></md-input>
|
||||
</md-card-content>
|
||||
</md-card>
|
||||
|
||||
<md-card class="demo-card demo-basic">
|
||||
<md-toolbar color="primary">Hints</md-toolbar>
|
||||
<md-card-content>
|
||||
<p>
|
||||
<md-input placeholder="Character count (100 max)" maxLength="100" class="demo-full-width"
|
||||
value="Hello world. How are you?"
|
||||
#characterCountHintExample>
|
||||
<md-hint align="end">{{characterCountHintExample.characterCount}} / 100</md-hint>
|
||||
</md-input>
|
||||
</p>
|
||||
</md-card-content>
|
||||
</md-card>
|
||||
|
||||
<md-card class="demo-card">
|
||||
<md-card-title>
|
||||
Hello <md-input [(ngModel)]="name" type="string" placeholder="First name"></md-input>,
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
@import 'default-theme';
|
||||
@import 'variables';
|
||||
|
||||
.demo-basic {
|
||||
padding: 0;
|
||||
}
|
||||
.demo-basic md-card-content {
|
||||
padding: 16px;
|
||||
}
|
||||
.demo-full-width {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.demo-icons {
|
||||
font-size: 100%;
|
||||
|
||||
@@ -3,6 +3,7 @@ import {MD_INPUT_DIRECTIVES} from '../../components/input/input';
|
||||
import {MdButton} from '../../components/button/button';
|
||||
import {MdCard} from '../../components/card/card';
|
||||
import {MdCheckbox} from '../../components/checkbox/checkbox';
|
||||
import {MdToolbar} from '../../components/toolbar/toolbar';
|
||||
|
||||
|
||||
let max = 5;
|
||||
@@ -11,7 +12,7 @@ let max = 5;
|
||||
selector: 'input-demo',
|
||||
templateUrl: 'demo-app/input/input-demo.html',
|
||||
styleUrls: ['demo-app/input/input-demo.css'],
|
||||
directives: [MdCard, MdCheckbox, MdButton, MD_INPUT_DIRECTIVES]
|
||||
directives: [MdCard, MdCheckbox, MdButton, MdToolbar, MD_INPUT_DIRECTIVES]
|
||||
})
|
||||
export class InputDemo {
|
||||
dividerColor: boolean;
|
||||
|
||||
Reference in New Issue
Block a user