Skip to content

docs(input, select): update docs and create more examples #7673

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

Merged
merged 6 commits into from
Oct 12, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
23 changes: 19 additions & 4 deletions guides/creating-a-custom-form-field-control.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ class MyTelInput {
```

### Providing our component as a MatFormFieldControl

The first step is to provide our new component as an implementation of the `MatFormFieldControl`
interface that the `<mat-form-field>` knows how to work with. To do this, we will have our class
implement `MatFormFieldControl`. Since this is a generic interface, we'll need to include a type
Expand All @@ -89,18 +90,19 @@ class MyTelInput implements MatFormFieldControl<MyTel> {

This sets up our component so it can work with `<mat-form-field>`, but now we need to implement the
various methods and properties declared by the interface we just implemented. To learn more about
the `MatFormFieldControl` interface, see its
[definition](https://github.com/angular/material2/blob/master/src/lib/form-field/form-field-control.ts).
(Unfortunately generated API docs are not available yet, but we'll go through the methods and
properties in this guide.)
the `MatFormFieldControl` interface, see the
[form field API documentation](https://material.angular.io/components/form-field/api).

### Implementing the methods and properties of MatFormFieldControl

#### `value`

This property allows someone to set or get the value of our control. Its type should be the same
type we used for the type parameter when we implemented `MatFormFieldControl`. Since our component
already has a value property, we don't need to do anything for this one.

#### `stateChanges`

Because the `<mat-form-field>` uses the `OnPush` change detection strategy, we need to let it know
when something happens in the form field control that may require the form field to run change
detection. We do this via the `stateChanges` property. So far the only thing the form field needs to
Expand All @@ -122,6 +124,7 @@ ngOnDestroy() {
```

#### `id`

This property should return the ID of an element in the component's template that we want the
`<mat-form-field>` to associate all of its labels and hints with. In this case, we'll use the host
element and just generate a unique ID for it.
Expand All @@ -133,6 +136,7 @@ static nextId = 0;
```

#### `placeholder`

This property allows us to tell the `<mat-form-field>` what to use as a placeholder. In this
example, we'll do the same thing as `matInput` and `<mat-select>` and allow the user to specify it
via an `@Input()`. Since the value of the placeholder may change over time, we need to make sure to
Expand All @@ -152,6 +156,7 @@ private _placeholder: string;
```

#### `ngControl`

This property allows the form field control to specify the `@angular/forms` control that is bound to
this component. Since we haven't set up our component to act as a `ControlValueAccessor`, we'll just
set this to `null` in our component. In any real component, you would probably want to implement
Expand All @@ -170,6 +175,7 @@ constructor(..., @Optional() @Self() public ngControl: NgControl) { ... }
```

#### `focused`

This property indicates whether or not the form field control should be considered to be in a
focused state. When it is in a focused state, the form field is displayed with a solid color
underline. For the purposes of our component, we want to consider it focused if any of the part
Expand All @@ -195,6 +201,7 @@ ngOnDestroy() {
```

#### `empty`

This property indicates whether the form field control is empty. For our control, we'll consider it
empty if all of the parts are empty.

Expand All @@ -206,6 +213,7 @@ get empty() {
```

#### `shouldPlaceholderFloat`

This property is used to indicate whether the placeholder should be in the floating position. We'll
use the same logic as `matInput` and float the placeholder when the input is focused or non-empty.
Since the placeholder will be overlapping our control when when it's not floating, we should hide
Expand All @@ -228,6 +236,7 @@ span {
```

#### `required`

This property is used to indicate whether the input is required. `<mat-form-field>` uses this
information to add a required indicator to the placeholder. Again, we'll want to make sure we run
change detection if the required state changes.
Expand All @@ -245,6 +254,7 @@ private _required = false;
```

#### `disabled`

This property tells the form field when it should be in the disabled state. In addition to reporting
the right state to the form field, we need to set the disabled state on the individual inputs that
make up our component.
Expand All @@ -269,6 +279,7 @@ private _disabled = false;
```

#### `errorState`

This property indicates whether the associated `NgControl` is in an error state. Since we're not
using an `NgControl` in this example, we don't need to do anything other than just set it to `false`.

Expand All @@ -277,6 +288,7 @@ errorState = false;
```

#### `controlType`

This property allows us to specify a unique string for the type of control in form field. The
`<mat-form-field>` will add an additional class based on this type that can be used to easily apply
special styles to a `<mat-form-field>` that contains a specific type of control. In this example
Expand All @@ -288,6 +300,7 @@ controlType = 'my-tel-input';
```

#### `setAriaDescribedByIds(ids: string[])`

This method is used by the `<mat-form-field>` to specify the IDs that should be used for the
`aria-describedby` attribute of your component. The method has one parameter, the list of IDs, we
just need to apply the given IDs to our host element.
Expand All @@ -301,6 +314,7 @@ setDescribedByIds(ids: string[]) {
```

#### `onContainerClick(event: MouseEvent)`

This method will be called when the form field is clicked on. It allows your component to hook in
and handle that click however it wants. The method has one parameter, the `MouseEvent` for the
click. In our case we'll just focus the first `<input>` if the user isn't about to click an
Expand All @@ -315,6 +329,7 @@ onContainerClick(event: MouseEvent) {
```

### Trying it out

Now that we've fully implemented the interface, we're ready to try our component out! All we need to
do is place it inside of a `<mat-form-field>`

Expand Down
21 changes: 16 additions & 5 deletions src/lib/form-field/form-field.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ In this document, "form field" refers to the wrapper component `<mat-form-field>
(e.g. the input, textarea, select, etc.)

The following Angular Material components are designed to work inside a `<mat-form-field>`:
* [&lt;input matInput&gt; &amp; &lt;textarea matInput&gt;](https://material.angular.io/components/input/overview)
* [&lt;mat-select&gt;](https://material.angular.io/components/select/overview)
* [&lt;mat-chip-list&gt;](https://material.angular.io/components/chips/overview)
* [`<input matInput>` &amp; `<textarea matInput>`](https://material.angular.io/components/input/overview)
* [`<mat-select>`](https://material.angular.io/components/select/overview)
* [`<mat-chip-list>`](https://material.angular.io/components/chips/overview)

<!-- example(form-field-overview) -->

### Floating placeholder

The floating placeholder is a text label displayed on top of the form field control when
the control does not contain any text. By default, when text is present the floating placeholder
floats above the form field control.
Expand Down Expand Up @@ -46,6 +47,7 @@ setting can be either `always`, `never`, or `auto`.
```

### Hint labels

Hint labels are additional descriptive text that appears below the form field's underline. A
`<mat-form-field>` can have up to two hint labels; one start-aligned (left in an LTR language, right
in RTL), and one end-aligned.
Expand All @@ -60,6 +62,7 @@ raise an error.
<!-- example(form-field-hint) -->

### Error messages

Error messages can be shown under the form field underline by adding `mat-error` elements inside the
form field. Errors are hidden initially and will be displayed on invalid form fields after the user
has interacted with the element or the parent form has been submitted. Since the errors occupy the
Expand All @@ -74,6 +77,7 @@ multiple errors is up to the user.
<!-- example(form-field-error) -->

### Prefix & suffix

Custom content can be included before and after the input tag, as a prefix or suffix. It will be
included within the visual container that wraps the form control as per the Material specification.

Expand All @@ -83,12 +87,14 @@ the prefix. Similarly, adding `matSuffix` will designate it as the suffix.
<!-- example(form-field-prefix-suffix) -->

### Custom form field controls

In addition to the form field controls that Angular Material provides, it is possible to create
custom form field controls that work with `<mat-form-field>` in the same way. For additional
information on this see the guide on
[Creating Custom mat-form-field Controls](https://material.angular.io/guide/creating-a-custom-form-field-control).

### Theming

`<mat-form-field>` has a `color` property which can be set to `primary`, `accent`, or `warn`. This
will set the color of the form field underline and floating placeholder based on the theme colors
of your app.
Expand All @@ -105,24 +111,29 @@ mat-form-field.mat-form-field {
<!-- example(form-field-theming) -->

### Accessibility
If a floating placeholder is specified, it will be automatically used as the label for the form field
control. If no floating placeholder is specified, the user should label the form field control

If a floating placeholder is specified, it will be automatically used as the label for the form
field control. If no floating placeholder is specified, the user should label the form field control
themselves using `aria-label`, `aria-labelledby` or `<label for=...>`.

Any errors and hints added to the form field are automatically added to the form field control's
`aria-describedby` set.

### Troubleshooting

#### Error: Placeholder attribute and child element were both specified

This error occurs when you have specified two conflicting placeholders. Make sure that you haven't
included both a `placeholder` property on your form field control and a `<mat-placeholder>`
element.

#### Error: A hint was already declared for align="..."

This error occurs if you have added multiple hints for the same side. Keep in mind that the
`hintLabel` property adds a hint to the start side.

#### Error: mat-form-field must contain a MatFormFieldControl

This error occurs when you have not added a form field control to your form field. If your form
field contains a native `<input>` or `<textarea>` element, make sure you've added the `matInput`
directive to it. Other components that can act as a form field control include `<mat-select>`,
Expand Down
Loading