© Venkata Keerti Kotaru 2020
V. K. KotaruAngular for Material Designhttps://doi.org/10.1007/978-1-4842-5434-9_8

8. Material Design: User Input

Venkata Keerti Kotaru1 
(1)
Hyderabad, India
 

One of the important aspects of an application is accepting user input. Users key in data through controls like text fields, single select or multiselect drop-downs, radio buttons, date controls, and so forth. The Angular Material library provides many such ready-made components that confine to Material Design guidelines.

This chapter explains how to use input fields for accepting user input. We begin with the design aspects of input elements. We discuss using text field and text area controls that confine to Material Design guidelines. Next, we cover using Material Design drop-downs, which are both single select and multiselect. We conclude by talking about chips, a Material Design component for multiselect drop-downs that can add values on the fly.

Material Input Elements

Material Design aesthetics define input elements like the text field, text area, drop-downs, and so forth, with the characteristics shown in Figure 8-1. The text field is an example.
../images/475625_1_En_8_Chapter/475625_1_En_8_Fig1_HTML.jpg
Figure 8-1

Sample Material Design input element

Notice that the text field is underlined. The behavior of the control is such that underlining is emphasized as the user focuses the cursor on the text field. The floating label shows the title of the text field. It moves away as the user focuses the cursor on the text field. The placeholder text shows in its place until the user types a value into the text field.

Material Design Form Fields

The Angular Material library provides the mat-form-field component, which is typically used to enclose the following controls.
  • Text field

  • Text area

  • Drop-down

  • Chip input (used for selecting multiple items for an input field)

On these controls, mat-form-field encapsulates the appearance, floating labels, hint text, and placeholders.

Note

The Angular Material library components and directives that are provided out of the box are prefixed with mat. We can identify Material components easily with this naming convention.

To use mat-form-field, import MatFormFieldModule from material/form-field in @angular monorepo. In the code sample we created in Chapter 1, notice that we created a separate module for Material Design components. The TypeScript class module was named SuperheroesMaterialDesignModule (located in src/app/superheroes-material-design/superheroes-material-design.module.ts). Listing 8-1 x is for the import module.
import { NgModule } from '@angular/core';
import { MatFormFieldModule } from '@angular/material/form-field'
// Removed code for brevity
@NgModule({
 declarations: [
// Removed code for brevity
 ],
 imports: [
   BrowserAnimationsModule,
   MatFormFieldModule
 ],
  exports: [
    CreateSuperheroComponent
  ],
// Removed code for brevity
})
export class SuperheroesMaterialDesignModule { }
Listing 8-1

Import Module for Using the mat-form-field Component

Note the exports array with createSuperheroComponent. We use the newly generated component in the main module (named AppModule); hence, it needs to be exported.

To use the component, add it to the AppComponent template file. This is temporary. Eventually, we will be able to use multiple components on different URLs in the application. See Listing 8-2.
--- app.component.html ---
<app-create-superhero></app-create-superhero>
Listing 8-2

Using the Create Superhero Component in the Main Module

Appearance

Appearance is an input attribute. The component provides the following options (also see Figure 8-2).
../images/475625_1_En_8_Chapter/475625_1_En_8_Fig2_HTML.jpg
Figure 8-2

Text field with various appearances

  • legacy

  • standard

  • fill

  • outline

Listing 8-3 is for the appearance input attribute in mat-form-field.
 <mat-form-field appearance="legacy">
        <!-- code for input field goes here -->
 </mat-form-field>
Listing 8-3

mat-form-field with the appearance Attribute

Text Field Within mat-form-field

You saw the look and feel and behavior of mat-form-field with a text field in Figure 8-1 and Figure 8-2. Let’s review creating a Material Design text field.

Angular provides the matInput directive out of the box. This directive is used in the <input /> element (text field). All Angular Material components and directives are prefixed with mat.

To use the directive, you need to import the module that the directive is available in. Listing 8-4 imports matInputModule from @angular material’s monorepo. It expands what we saw in Listing 8-3.
import { NgModule } from '@angular/core';
import { MatFormFieldModule } from '@angular/material/form-field'
import { MatInputModule } from '@angular/material/input';
// Removed code for brevity
@NgModule({
 declarations: [
  // Removed code for brevity
 ],
 imports: [
   MatInputModule,
   MatFormFieldModule,
// Removed code for brevity
 ],// Removed code for brevity
})
export class SuperheroesMaterialDesignModule { }
Listing 8-4

Import MatInputModule

Superheroes Code Sample

Before we start using the directive and other components, consider enhancing the superheroes code sample. Since we are working with user input in this chapter, let’s create a component that accepts superhero data as input. Let’s call it the create-superhero component. Use the command in Listing 8-5 to create the component.
ng g c superheroes-material-design/create-superhero
Listing 8-5

Generate the create-superhero Component

Here we are using Angular CLI to generate a new component; hence, the ng command. Use the g flag to generate it. The c flag refers to a component. The component is under the superheroes-material-design module and folder; hence, the create-superhero component name is prefixed with superheroes-material-design/.

The Angular CLI command in Listing 8-5 is abbreviated. For clarity, if you prefer to use the complete command, consider the following:

ng generate component superheroes-material-design/create-superhero

The command creates a new component with the files shown in Figure 8-3.
../images/475625_1_En_8_Chapter/475625_1_En_8_Fig3_HTML.jpg
Figure 8-3

The Angular CLI generated create-superhero component

Now that we have created a new component for a superhero input form, and the directive is available to use, edit the create-superhero.component.html template file. Add the matInput directive in the <input /> element. Remember, mat-form-field encloses input elements and form fields. Include the input element as part of the mat-form-field component (see Listing 8-6 and Figure 8-4). It gives the Material Design look and feel and adds an underline, which is emphasized on focus (keyboard cursor). The placeholder text shows until the user types.
<div>
 <mat-form-field appearance="standard">
   <input type="text" matInput placeholder="A name to be remembered" />
 </mat-form-field>
</div>
Listing 8-6

Use matInput to Create the Material Text Field

../images/475625_1_En_8_Chapter/475625_1_En_8_Fig4_HTML.jpg
Figure 8-4

Material text field

Floating Label

Within mat-form-field, use mat-label to add a title or a floating label. It is part of MatFormFieldModule, which is already imported. By default, a floating label shows within the text field and moves away as the user focuses the keyboard cursor to type text (see Listing 8-7 and Figure 8-5).
 <mat-form-field floatLabel="float" appearance="standard">
   <mat-label>Superhero Name</mat-label>
   <input type="text" required matInput placeholder="A name to be remembered" />
 </mat-form-field>
Listing 8-7

Material Text Field with the Float Label

../images/475625_1_En_8_Chapter/475625_1_En_8_Fig5_HTML.jpg
Figure 8-5

Material text field with float label

Note the floatLabel input attribute. In Listing 8-7, it has a default value float. You may change it to one of the following.
  • always to float on top of the text field, even when the keyboard cursor is not focused on the text field.

  • none to never float. It can only be used with the appearance value legacy in mat-form-field.

  • float is the default value. It floats to the top when the keyboard cursor focuses on the text field.

When the appearance value (in the mat-form-field component) is a legacy, the placeholder text in the input element (text field) substitutes as a floating label. This behavior doesn’t apply to other appearances, or standard, fill, and outline. The latter needs an explicit mat-label component that is used for a floating label.

Required Field

Use the required attribute in the input element to mark the required input field. It adds an asterisk to the floating label (see Listing 8-8 and Figure 8-6).
<div>
 <!-- Appearance: Outline -->
 <mat-form-field appearance="outline">
   <mat-label>Superhero Name</mat-label>
   <input type="text" matInput required placeholder="A name to be remembered"/>
   <mat-hint>Enter name</mat-hint>
 </mat-form-field>
</div>
Listing 8-8

Required Input Field

../images/475625_1_En_8_Chapter/475625_1_En_8_Fig6_HTML.jpg
Figure 8-6

Required field adds asterisk to floating label

If you do not wish to show the required field indicator (asterisk), use the hideRequiredMarker input attribute in mat-form-field (see Listing 8-9). The form field is still a required field. You can hide the asterisk if there is a custom implementation to highlight the required fields.
 <mat-form-field hideRequiredMarker appearance="standard">
    <!-- removed code for brevity -->
   <input type="text" matInput required placeholder="A name to be remembered"/>
 </mat-form-field>
Listing 8-9

Hide Asterisk, Indicating a Required Field

Hint Text

Use the mat-hint component to provide hint text. It is part of MatFormFieldModule, which is already imported. The component has two input attributes.
  • align: Uses an “end” value to right align the hint text. The default value is start.

  • id: The unique ID for the hint text.

Note

Optionally, you may use the hintLabel input attribute in mat-form-field instead of using a separate mat-label component; however, you cannot position the label’s start or end with this input attribute.

Listing 8-10 is the complete code snippet of a text field. Figure 8-7 shows the hint text and floating label.
<div>
 <!-- Appearance: Standard -->
 <mat-form-field appearance="standard">
   <mat-label>Superhero Name</mat-label>
   <input type="text" matInput placeholder="A name to be remembered" />
   <mat-hint>Enter name</mat-hint>
 </mat-form-field>
</div>
Listing 8-10

Input Text Field with Floating Label and Hint Text

Note

You may use the matPrefix and matSuffix directives to show a prefix and a suffix. For a currency value, the dollar symbol could prefix the text field.

Input Types with matInput

You have seen using the matInput directive with <input type=”text” />. The following are other types that are supported by the directive.
  • Date and time–related types
    • date

    • datetime-local

    • month

    • time

    • week

  • User data types
    • password

    • email

    • tel

    • url

  • Other frequently used types
    • number

    • search

    • color

The following input types are not supported.
  • checkbox

  • file

  • hidden

  • image

  • radio

  • range

  • reset

  • submit

Note

Even though the matInput directive does not support check boxes, mat-check box, which is an Angular Material component, provides this functionality with Material Design look and feel and behavior. You need to import MatCheckboxModule to use this component.

Text Area Within mat-form-field

You can have a text area with mat-form-field and the matInput directive. In Listing 8-11, the explanation of superhero powers needs more than a single-line text field. You can use textarea for this.
<mat-form-field appearance="outline">
  <mat-label>Powers</mat-label>
  <textarea rows="6" matInput></textarea>
  <mat-hint>Explain superhero powers</mat-hint>
</mat-form-field>
Listing 8-11

Text Area with mat-form-field and matInput

Figure 8-7 shows the result.
../images/475625_1_En_8_Chapter/475625_1_En_8_Fig7_HTML.jpg
Figure 8-7

Text area with matInput

Autosize the Text Area

You can enter more than one line (or rows) of text in a text area. To configure a number of rows, use the “rows” attribute in the <textarea /> element. For example, if we use a value of 5 for the number of rows, textarea adds a scrollbar when the user types the sixth row of text.

It is useful if the text area grows and shrinks as the user types. Use the cdkTextareaAutosize directive to add or remove rows, depending on the text. However, it might be inconvenient if the text area starts very small and grows indefinitely. You can set a minimum and maximum number of rows. To do this, use cdkAutosizeMinRows and cdkAutosizeMaxRows, respectively. The text area in Listing 8-12 starts with four rows and grows to a maximum height of ten rows. It adds a scrollbar at the eleventh row.
<div>
 <mat-form-field appearance="outline">
   <mat-label>Powers</mat-label>
   <textarea cdkTextareaAutosize cdkAutosizeMinRows="4" cdkAutosizeMaxRows="10" rows="6" matInput></textarea>
   <mat-hint>Explain superhero powers</mat-hint>
 </mat-form-field>
</div>
Listing 8-12

Textarea with cdkTextareaAutosize

In Figure 8-8, the text area starts with a height of four rows, even though the text is only in two of the rows. It grows to ten rows without a scrollbar.
../images/475625_1_En_8_Chapter/475625_1_En_8_Fig8_HTML.jpg
Figure 8-8

The text area with a minimum of four rows height and a maximum of ten rows

Material Drop-downs

Form controls for data input commonly select a value from a drop-down. The Angular Material library provides mat-select and mat-option components that confine to the Material Design look and feel. Components are wrapped in mat-form-field (same as the text field).

To begin, import MatSelectModule, which makes the mat-select and mat-option components available in the application (see Listing 8-13).
import { MatSelectModule } from '@angular/material/select';
@NgModule({
  // removed code for brevity
  imports: [
    BrowserAnimationsModule,
    MatSelectModule,
    MatInputModule,
    MatFormFieldModule
  ],
})
export class SuperheroesMaterialDesignModule { }
Listing 8-13

Import Module for Material Design Select Component

In Listing 8-14, the mat-select component encapsulates all available options. The mat-option component is repeated to show each component.
<div>
 <!-- Appearance: Outline -->
 <mat-form-field appearance="outline">
   <mat-label>Country</mat-label>
   <mat-select>
     <mat-option>India</mat-option>
     <mat-option>United States</mat-option>
     <mat-option>Outer space</mat-option>
   </mat-select>
 </mat-form-field>
</div>
Listing 8-14

Using mat-select and mat-option

The result is shown in Figure 8-9. Notice that the mat-form-field appearance is set to outline.
../images/475625_1_En_8_Chapter/475625_1_En_8_Fig9_HTML.jpg
Figure 8-9

Material Design drop-down

Note the Material Design look and feel and behavior in the drop-down. The “Country” mat-label value shows by default in the drop-down. When the user selects a value, it moves up to a floating label.

Use the value field in the mat-select and mat-option components.
  • In the mat-option component, it uniquely identifies an option or a value. Typically, you use an ID for the option (see Listing 8-15).

  • In mat-select, notice the two-way data binding with a variable in the component class.

1. <div>
2. <!-- Appearance: Outline -->
3. <mat-form-field appearance="outline">
4.   <mat-label>Country</mat-label>
5.   <mat-select [(value)]="country">
6.      <mat-option>None</mat-option>
7.     <mat-option value="in">India</mat-option>
8.     <mat-option value="us">United States</mat-option>
9.     <mat-option value="os">Outer Space</mat-option>
10.   </mat-select>
11. </mat-form-field>
12. <strong>Superhero comes from " {{country}} "</strong>
13. </div>
Listing 8-15

Using the value Attribute in a Select Box

Note that a label within a strong element is shown for demonstration purposes (see line 12). The selected value is shown on the label instantly—as soon as the user selects an option on the drop-down. The value attribute on mat-select acts like ng-model, as seen in data binding (see Figure 8-10). The "os" label is the value in mat-option (see line 9).
../images/475625_1_En_8_Chapter/475625_1_En_8_Fig10_HTML.jpg
Figure 8-10

Two-way data binding with a value field

Note

The None mat-option is without a value. After selecting a value, if the user needs to reset the country, an option without a value could be used. It is useful because the user can’t delete a selected value (unlike a text field). We may show one or more options disabled. Add the disabled attribute in mat-option.

Categorize Options

Grouping options can be useful, especially when there are too many options to select from. Use the mat-optgroup component to group options. Use the label attribute in mat-optgroup to label the group.

Consider line 7 and line 11 in Listing 8-16. Note the category title specified in the component. Figure 8-11 shows the result.
1. <div>
2. <!-- Appearance: Outline -->
3. <mat-form-field appearance="outline">
4.   <mat-label>Country</mat-label>
5.   <mat-select placeholder="select country" [(value)]="country">
6.     <mat-option>None</mat-option>
7.     <mat-optgroup label="Earth">
8.       <mat-option value="in">India</mat-option>
9.       <mat-option value="us">United States</mat-option>
10.     </mat-optgroup>
11.     <mat-optgroup label="Outer Space">
12.       <mat-option value="os">Asgard</mat-option>
13.     </mat-optgroup>
14.   </mat-select>
15. </mat-form-field>
16. </div>
Listing 8-16

Group Options

../images/475625_1_En_8_Chapter/475625_1_En_8_Fig11_HTML.jpg
Figure 8-11

Categorized options

Multiselect

By default, a drop-down is used to select one item for a field. You may use it for multiselect. While the drop-down is expanded, the component uses check boxes that indicate the selected options (see Figure 8-12). When done (collapsed), it shows all the selected options.
../images/475625_1_En_8_Chapter/475625_1_En_8_Fig12_HTML.jpg
Figure 8-12

Multiselect drop-down

To use multiselect add the “multiple” attribute on the mat-select element (see line 5 in Listing 8-17).
1. <div>
2.   <!-- Appearance: Outline -->
3.   <mat-form-field appearance="outline">
4.     <mat-label>Special Powers</mat-label>
5.     <mat-select [(value)]="powers" multiple>
6.       <mat-option>None</mat-option>
7.       <mat-option value="fly">fly</mat-option>
8.       <mat-option value="hammer">wield hammer</mat-option>
9.       <mat-option value="power">grow powerful</mat-option>
10.     </mat-select>
11.   </mat-form-field>
12.   <strong> My superhero can " {{powers}} "</strong>
13. </div>
Listing 8-17

mat-select with Multiselect Enabled

Figure 8-13 shows the result. The value binding captures multiple selected values as a comma separated string.
../images/475625_1_En_8_Chapter/475625_1_En_8_Fig13_HTML.jpg
Figure 8-13

Value field with multiple options selected

Material Design: Chips

Chips is an interface for selecting one or more items in a list. It is used similarly to a multiselect drop-down. The chips component allows entering a new value. The presentation of selected items is different. In Figure 8-14, the cross button lets you easily remove a selected item.
../images/475625_1_En_8_Chapter/475625_1_En_8_Fig14_HTML.jpg
Figure 8-14

Material Design: Chips

The chip values are in a text field. A new value can be typed in there.

As with any other Angular Material library component, to use chips, you import the required modules. In Listing 8-18, we need mat-chips-module and mat-icons-module to use chips in the application.
import { MatChipsModule } from '@angular/material/chips';
import { MatIconModule } from '@angular/material/icon';
@NgModule({
 // Removed code for brevity
 imports: [
   MatChipsModule,
   MatIconModule
 ],)
export class SuperheroesMaterialDesignModule { }
Listing 8-18

Import Chips Modules

Chips are enclosed in mat-form-field, similar to the input element’s matInput directive and the mat-select component. Chips are a list of items; hence, they are enclosed in a mat-chip-list directive. Each chip item is rendered by a mat-chip element (see Listing 8-19).
1. <div>
2.     <mat-form-field appearance="standard">
3.       <mat-label>Likes to eat</mat-label>
4.       <mat-chip-list #favFood>
5.         <mat-chip >
6.           Laddu
7.         </mat-chip>
8.         <mat-chip >
9.             Cheeseburger
10.        </mat-chip>
11.       </mat-chip-list>
12.       <input
13.         [matChipInputFor]="favFood" />
14.      </mat-form-field>
15. </div>
Listing 8-19

Basic Chip List

Note #favFood. It is a template reference variable. It is discussed in detail in an upcoming chapter. For the moment, know that a chip list is identified with a template-level variable named favFood. We use the matChipInputFor directive in an input element, and map the variable to the element. Figure 8-15 shows the result. It is basic compared to the original chips shown in Figure 8-14.
../images/475625_1_En_8_Chapter/475625_1_En_8_Fig15_HTML.jpg
Figure 8-15

Basic chip list

Add Items to a Chip List

In Listing 8-20, the two values (Laddu and Cheeseburger) are coded in the HTML template. In the sample, they are static, and the list does not change. See the lines between 4 and 11.

You may use a dynamic list in an array in the TypeScript class component (see Listing 8-20). For simplicity, the array variable in the TypeScript file component has hard-coded values. However, in a real scenario, you might retrieve these values from a remote service.
--- create-superhero.component.ts ---
1. items: Array<string> = ["Laddu", "Cheeseburger", "Pizza" ];
--- create-superhero.component.html ---
1.     <mat-form-field appearance="standard">
2.       <mat-label>Likes to eat</mat-label>
3.       <mat-chip-list #favFood>
4.         <mat-chip *ngFor="let item of items">
5.           {{item}}
6.         </mat-chip>
7.       </mat-chip-list>
8.       <input
9.         [matChipInputFor]="favFood"
10.         (matChipInputTokenEnd)="add($event)"
11.         matChipInputAddOnBlur />
12.      </mat-form-field>
Listing 8-20

A Dynamic Chip List

Note line 4 in the component’s HTML file. Use the ∗ngFor directive in mat-chip to iterate through the array. For each value in the array, a mat-chip element is created. We look at the ngFor directive in another chapter. For the moment, understand that it is a for-loop in the HTML template.

As described earlier, a chip list allows you to add custom dynamic values to a list. The user may enter a new value in the text field. It will be added to the chip list. To do so, add a matChipInputTokenEnd event handler to the text field. Note line 10 in Listing 8-20. The event is raised as the user adds a new value to the list. In other words, it is triggered when the user submits or presses Enter in a text field.

Use the matChipInputTokenEnd event to capture a new value entered by the user. Create a new chip by adding it to the item array. (In the preceding example, the array variable is named items). Listing 8-21 pushes the new item added by the user into an array object.
--- create-superhero.component.ts ---
  addItem(event){
    this.items.push(event.value);
  }
Listing 8-21

Capture the Event Value from matChipInputTokenEnd

An additional input attribute, matChipInputAddOnBlur, triggers the matChipInputTokenEnd event on a blur (losing focus), in addition to pressing the Enter key.

Remove Items from a Chip List

So far, we have created chips that do not have a remove option. Revisit Figure 8-14 and Figure 8-15. The former comes with a remove icon, which isn’t shown in Figure 8-15. Without this option, the user cannot remove an item that was accidentally selected.

Let’s add the remove option to the chips. To show a cancel button, add a cancel icon to each chip (see Listing 8-22). Note line 4 in the HTML template file. It adds the cancel icon. It is enclosed in the mat-chip component; hence, the Cancel button becomes part of the chip. Remember, we already imported MatIconModule.
--- create-superhero.component.ts ---
1.  removeHandler(item: string){
2.    this.items.splice(this.items.indexOf(item), 1);
3.  }
--- create-superhero.component.html ---
1.   <mat-chip-list #favFood>
2.      <mat-chip *ngFor="let item of items" (removed)="removeHandler(item)">
3.         {{item}}
4.         <mat-icon matChipRemove>cancel</mat-icon>
5.      </mat-chip>
6.   </mat-chip-list>
Listing 8-22

mat-icon for Cancel Added

In the HTML template, the “removed” event handler is added to mat-chip (line 2). We use it to handle remove actions. It raises MatChipEvent. However, in the example, we pass the selected chip item as the value. Note the removeHandler code in the TypeScript file component. Line 2 in this file splices the items array (which was used to show the chip list). In other words, it removes the item from the list.

With this addition of code, we achieve the intended result, as shown in Figure 8-15.

Note

We can mark some or all of the chips as removable. By default, all chips are removable. We can add a removable field in mat-chip and set the value as false to disable the ability to remove a chip.

Conclusion

The chapter covered the basics of accepting user input text and values. It explained how to use Angular Material library components. The chapter began with the look and feel and behavior of a Material Design input field. This section included floating labels, hint text, placeholder text, and so forth.

The chapter also introduced mat-form-field, which encapsulates text fields, text areas, drop-downs, and chips. It discussed using textfield and textarea with the matInput directive for providing a Material Design look and feel. Next, it detailed building input fields with Material Design drop-down components, mat-select, and mat-options. It described many features, including multiselect with drop-downs.

The chapter introduced chips and chip lists, which allow dynamic and custom multiselection with values created on the fly. It introduced mat-chip and mat-chiplist components and various input and output attributes and directives to build chips.

Exercise

Build a “create dinosaur” form. Allow the user to provide the following input.
  • Dinosaur name: Build a text field with a standard appearance.

  • Dinosaur family: Build a drop-down with the following values.
    • Abelisauridae

    • Noasauridae

    • Megalosauridae

  • Timeframe: Build a text field and a postfix with Mil-yrs-ago (Millions of years ago)

  • Dinosaur description: Build a text area with a minimum of 6 rows and a maximum of 20.

  • Continents they lived in: Use a chip list that accepts dynamic values from the user.

Reference

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.82.244