Apply multi-layout to an Angular app

featured_image

In case of complex projects it is often expected to provide different layouts adapted to the needs of users – the logged-in user requires different UI elements than the guest. We have to customise the appearance of applications time and again taking into account many various aspects. Angular allows you to organise the presentation layer to easily handle multiple layouts.

What we are going to build

Our application will provide two separate layouts – one served on a landing page view, the other used on a dashboard view. In this post we will display the default contents, just to present how to serve different components in isolated layouts.

To see the version with a horizontal navigation and a footer for the landing page and a vertical navigation for a dashboard, check out the Enhance the presentation layer of your multi-layout Angular app post, where all views are complemented with the appropriate html code and Bootstrap classes. The finished project is available in the following GitHub repository: little-pinecone/angular-multi-layout-scaffolding.

Requirements

I try to keep the project up to date. Visit the releases list to keep track of the current versions of frameworks and libraries used.
  • Angular CLI – a command line interface tool that generates projects, components, modules, services.
    I’m working on:
  • We will work on a freshly created Angular 6 project that uses the scss preprocessor and Bootstrap styles. To learn how to create such a project, visit the How to create a new Angular project post. If you want to change the preprocessor, read the How to change a CSS preprocessor in an Angular project post.

Design overview

The layout folder will contain all components used to assemble the guest and authorised layouts and a component that is shared by both of them – PageContent. The actual content of two views – the landing page and the dashboard – is going to be stored in the pages folder. We are also going to create a routing module, so the layout served depends on the url.

You won’t find any authorisation logic in this example.

The final project src/ directory tree:

project tree screenshot

Angular CLI will create all parent folders for generated components – just remember to give the full path for a component.

Enable serving the content of different pages

To avoid code repetition and facilitate handling pages, we will create a component accessible for both layouts – the PageContent component:

Replace the default content of the page-content.component.html with the following code:

The work done in this section is contained in the commit 9d92b44a7c2b620e0d5391b7cd89ecf47cb88b58.

Manage the guest layout

Create the layout components

Create the component for the top navigation:

Create the component for the footer:

Bind the navigation, page content and footer within the guest layout:

Replace the content of the guest-layout.component.html with the following code:

Generate the component for our landing page:

Add routing to a page with the guest layout

Prepare the routing module file

The following steps are well covered in the official Angular tutorial.

Let’s create a routing module in the main directory of the project:

Angular CLI will create required files in the app/ folder and register the new module in the imports array of the AppModule.

In the app-routing.module.spec.ts file we can delete @NgModule.declarations array and CommonModule references:

From the @angular/router library import RouterModule and Routes:

Add @NgModule.exports array with RouterModule in it:

Add routes

We will need two separate sections for routes, but for now we can handle only the guest layout. Import GuestLayoutComponent and LandingPageComponent and add the following route to the routes array:

Add RouterModule.forRoot(routes) to the @NgModule.imports array:

Do not display the default Angular page

We want to change the content displayed on http://localhost:4200/ – from the default Angular page to our landing page. Replace the content of app.component.html with the following code:

Check out the landing page of your app on http://localhost:4200/:

landing page base screenshot

The work done in this section is contained in the commit a5cb113c477777dd266457341313e070999d930e.

Troubleshooting

Make sure that the CLI is tracking changes, refresh the browser window with Ctrl+F5 or restart the Angular server if you can’t see the effect.

Fix the tests

If you run the following command:

you will see that the default test set from app.component.spec.ts fails. Let’s investigate the errors:

  1. <router-outlet> is not recognised

    Importing RouterTestingModule to the page-content.component.spec.ts and app.component.spec.ts files provides the Router mock:
  2. A component with nested components

    The guest-layout template have nested components – they should have their own tests so we can exclude them from testing in guest-layout. Import Component, create mocks and add the mocked components to the declarations section:

    You can apply NO_ERRORS_SCHEMA instead, but it will hide other errors – missing components and attributes that you overlooked or misspelled.
  3. Missing html content

    We altered the html that is tested- adjusting the content expected by tests fixes the problem. Furthermore, we can remove all tests from the app.component.spec.ts file – except the one testing the creation of the app:

AppComponent, GuestLayoutComponent and PageContentComponent don’t have any logic or html elements to test – we only need to verify whether they were created. You can read more about testing components in the official guide.

The work done in this section is contained in the commit c4e7e2d570c6fed56a5db249325710f5b620074d.

Troubleshooting

If the errors remain, try terminating the testing process and run the $ ng test command again.

Manage the layout for an authorised user

Create the component for the side navigation:

Bind the navigation and page content within the layout for and authorised user:

Replace the content of the authorised-layout.component.html with the following code:

Generate a component for the dashboard page:

Add routing to the dashboard page

Import AuthorisedLayoutComponent and DashboardComponent and add the following route to the routes array:

Check out the authorised layout on http://localhost:4200/dashboard:

dashboard base screenshot

The work done in this section is contained in the commit 7fd037e2ea0ed74f176dd7a1edee6b3740560b80.

Update the tests

If you run the following command:

you will see that the tests from authorised-layout.component.spec.ts fail. Again, we encounter the error caused by the nested components:

The authorised-layout template have nested components – they should have their own tests so we can exclude them from testing in authorised-layout. Import Component, create mocks and add the mocked components to the declarations section:

The work done in this section is contained in the commit 24cba57ee1b58b8c1abb6110212c6f78d71fd021.

Troubleshooting

If the errors remain, try terminating the process and run the $ ng test command again.

What is next?

Add html content and styles to the landing page, dashboard and both layouts components. Check out the Enhance the presentation layer of your multi-layout Angular app post or visit the project repository to see how to style the pages:

The landing page screenshot
The enhanced landing page

Photo by Toa Heftiba on StockSnap

One thought on “Apply multi-layout to an Angular app

Leave a Reply

Your email address will not be published. Required fields are marked *