The previous chapter described implementing SPAs (single-page applications) and routing techniques that navigate between pages. This chapter covers Material Design components for navigation.
The chapter discusses two Angular Material components: toolbar and sidenav. The most common use of the component is application-level navigation between pages. These components are easy to implement and provide a great user experience with the tried and tested Material Design patterns.
Toolbar
Toolbars are typically placed on top of a web page. It provides a title and list of actions that the user may perform on the page. A toolbar encompasses the top navigation of the page.
Getting Started
To use Angular Material’s toolbar, import the module containing the component. In Listing 12-1, all the Material Design components are encompassed in superheroes-material-design.module.ts.
Import Toolbar Module
The <mat-toolbar> component is now available for the application to use. Typically, a toolbar contains the top navigation of a page.
In the sample application, we organize the toolbar as follows. We place the toolbar at the same level as <router-outlet>. The router outlet updates the content and the components based on the route or the URL. Refer to Chapter 11 for more information on <router-outlet>.
In the sample application’s Superheroes Material Design module, let’s create a component that wraps the Angular Material toolbar. We use this component when we need to reference the toolbar. Creating a separate component allows us to customize our application’s toolbar. We will reuse the component throughout the application.
Create a Component for the Toolbar
Toolbar with a Welcome Title
Toolbar TypeScript File Component
We created the component as part of the Superhero Material Design module. In addition to creating new files, Angular CLI updates the Angular module file (see line 2 and line 6). Listing 12-5 is the superheroes-material-design.module.ts file. Angular CLI imports the new component, SuperheroToolbarComponent, and includes it in the declaration array.
Figure 12-2 depicts the toolbar next to <router-outlet>, which is in <app-component>. It is outside SuperheroesMaterialDesignModule. Hence, to use it in AppModule (containing <app-component>), we need to export the component. In Listing 12-5, see line 12. It exports the component from the module.
Note
Consider using --export option with Angular CLI, while generating the component. It generates the code that declares and exports the component from SuperheroesMaterialDesignModule. See Listing 12-6 for the export option included. If we did not use this option while creating the component, we may edit superhero-material-design.module.ts to add the component to exports.
Create a Component for Toolbar with --export Option
Export Toolbar Component from SuperheroMaterialDesignModule
App Module that imports SuperheroesMaterialDesignModule
App Component Using Superhero Toolbar and router-outlet
This achieves the structure and organization for the application specified in Figure 12-2.
Actions on the Toolbar
We already created a basic toolbar with just a title. It can contain additional elements. The toolbar is a natural location to place page-level actions. An action could be an operation, like save content, or a trigger for navigation. The toolbar typically contains high-level navigation actions that take the user to a new module or a functionality.
Considering that a page title is already on the toolbar and aligned to the left, let’s place the actions aligned to the right.
Place Actions on Toolbar
Flex the Element to Take up Remaining Space
flex-grow: The first value in Listing 12-10 represents flex-grow. The value is a number indicating how much the given element should grow (or stretch) in relation to the other flex elements around it. With a value of 1, it grows in the available space.
flex-shrink: The second value in Listing 12-10 represents flex-shrink. The value is a number indicating how much the given element should shrink (or collapse) in relation to the other flex elements around it.
flex-basis: The third value in Listing 12-10 represents flex-basis. It is the length of the item. Possible values are auto, inherit, or percentage, or a pixel value.
Multiple Rows in the Toolbar
A toolbar can have multiple rows. Use mat-toolbar-row to create a toolbar row. Listing 12-11 shows a subheader in the additional row. As an example, we may use the top row as an application title and the second row as the screen-level title.
Multiple Rows in Toolbar
Toolbar Theme
Primary: The most used primary color on the page.
Accent: The secondary, optional color on a page. Usage of the color helps distinguish the application.
Warn: The color used when a component needs attention; for example, a delete action, an unsaved cancel action, and so forth.
Color on the Toolbar
Integration with Angular Router
So far, we have created a toolbar, and added and positioned links (or buttons) on it. We created a view link and a create link on the toolbar. The links integrate with the router to navigate to various routes in the application.
Router Integration with the Toolbar
Import Router Module to Superheroes Material Design Module
There is an alternative approach if we wish to exclude routerLink and the routing logic out of the superheroes Material Design module. Considering the module is aimed to purely provide a Material Design look and feel and behavior to the application, we may move out the routerLink directive implementation from the module and the component.
However, we still have the toolbar for top navigation. It needs the route changes as the user attempts to navigate. We may use content projection with ng-content. Supply the navigation links, including the routerLink integration to the toolbar component. The parent component to the toolbar (AppComponent) may supply the links.
Note
Refer to Chapter 4 to read more about ng-content.
Use ng-content to Show Dynamic Content from AppComponent
Router Links Provided in AppComponent
With this approach, we separated the routing logic and the modules from the Angular Material components’ implementation.
Sidenav
Sidenav is often used as a navigation control. It can pull from the right or left of a page. It may have application-level or contextual page-level actions. The actions could take the user to a different route or page. We may also use them as actions on data on the page.
Note
Sidenav is often used for navigation elements; however, it is not necessary. It can be used as a container with a form or content that shows and hides as needed.
Getting Started
To use Angular Material’s sidenav, import the module containing the components and the directives. In Listing 12-17, all the Material Design components are encompassed in superheroes-material-design.module.ts.
Import Sidenav Module
Create sidenav Component for Superheroes Application
Export the sidenav Component from SuperheroesMaterialDesignModule
Note
Consider using --export option with Angular CLI while generating the component. It generates the code that declares and exports the component from SuperheroesMaterialDesignModule. See Listing 12-20 for the included export option. If we did not use this option while creating the component, we may edit superhero-material-design.module.ts to add the component to the exports.
Create and Export sidenav Component for Superheroes Application
Sidenav Content
Position: The possible values are “start” and “end”. The default value is “start”, which refers to the left side of the page. We may change it to “end” for the right side of the page. Figure 12-5 shows the sidenav on right (end).
Mode: The possible values are “over”, “push”, and “side”. We see it with the “over” value in Figure 12-x. Figure 12-x shows the “side” sidenav mode .
Opened: We may set the value to be true/false. If true, the application loads with the sidenav open.
Open(): A function call on the component to open or hide the sidenav.
Close(): A function call on the component to close or hide the sidenav.
Sidenav with Additional Configurations
Organizing the Sample Application for Sidenav
So far, we have created a component (SuperheroSidenavComponent) in SuperheroesMaterialDesignModule and used the mat-sidenav component. We have not yet used the newly created component in the application. Remember, we exported the SuperheroSidenavComponent in Listing 12-22. It is now available for module referencing SuperheroesMaterialDesignModule, which is the main module(AppModule) in the sample application.
The sidenav container is the parent component of everything that the sidenav implements. The component selector for usage in HTML template is mat-sidenav-container. For the sidenav content component, the selector is mat-sidenav-content. For a sidenav component, the selector is mat-sidenav.
Note
There can only be one sidenav in an application.
The sidenav content is the workspace of the application. Chapter 11 describes the <router-outlet> loads content of the application at a given route. For most applications, it is the workspace. If the application is using a sidenav, one implementation is to encapsulate <router-outlet> within the sidenav content.
Remember, <router-outlet> is on AppComponent. We may use mat-sidenav-container (the parent component) and mat-sidenav-content in AppComponent. However, so far, we have packaged all Angular Material implementation in SuperheroesMaterialDesignModule. Continuing with this approach, we may want to stay away from using the Angular Material components (mat-sidenav-container and mat-sidenav-component) directly in AppComponent, which belongs to AppModule.
Note
mat-sidenav is referenced in SuperheroSidenavComponent, which is part of SuperheroesMaterialDesignModule. It is already part of the desired module.
Generate Components for Sidenav Container and Content
Sidenav Container in app-superhero-sidenav-container
ng-content includes child components and app-superhero-sidenav-container content. All the contents of app-superhero-sidenav-container are transcluded under mat-sidenav-container.
Sidenav Content in app-superhero-sidenav-content
The mat-sidenav-content component needs the container to be its immediate parent. Hence, we added another mat-sidenav-container. Child components and contents of app-superhero-content are transcluded to the ng-content in Listing 12-26.
AppComponent Code Resulting in Sidenav Layout
Using a Menu Button to Toggle sidenav
Toolbar with Menu Icon
Toolbar Component Raising the Event on Click Of Menu
The menuClick output event is of type EventEmitter. The generic type on EventEmitter is boolean. The toolbar component toggles a boolean variable each time the user clicks the menu. The event is emitted.
AppComponent Handling the Event Raised by Toolbar
AppComponent TypeScript Code Handling Event
The sidenav instance calls open() or close() functions toggling the sidenav. Notice the view child sidenav representing the template reference variable sidenav. The call open() or close() is #2 in Figure 12-9.
SuperheroSidenavComponent Template
SuperheroSidenavComponent with Code to Toggle sidenav
The open() and close() functions called from app.component.ts toggle mat-sidenav. They call the API on the mat-sidenav instance. Lines 7 to 9 in Listing 12-32 show the open() function implementation. Lines 10 to 12 show the close() function implementation.
Conclusion
The Angular Material components described in this chapter help you build navigation patterns for an Angular application. They use Material Design concepts and provide a greater user experience. The Angular Material component provides a title for the application and is a great location for actions and links to other pages in the application.
The chapter described placing actions and links on the toolbar. It covered using Angular Material themes and colors with the component. It explained sidenav, sample layouts, implementing the layout with Angular Material components, and handling events across components between the toolbar and the sidenav.
Exercise
In the Angular routing exercise, we added routing to the dinosaur application. We created two routes: /dino-list and /dinosaur/:dinosaurName.
Provide links to navigate to these pages in a sidenav position on the right.
Add a toolbar that shows a title: Dinosaur App. On the right corner of the toolbar, add a toggle sidenav link. Clicking the link should toggle the sidenav.
Reference
Material Design documentation (https://material.angular.io/)