Angular Component Architecture

A simple set up for most use cases

Jonathan Siddle

--

This post will look at the general approach I use when developing Angular components, I will describe the architecture in abstract terms and then dig into an example using components shown in the gif above!

Note, full source for this post can be found here (The project contains and ASP Core and Angular application): https://github.com/JonathanSiddle/TestDoServer.

Architecture Overview

Angular is an opinionated framework, a LOT of attention has been given to the way the framework has been designed and the way it enforces component design, such as incorporating dependency injection by default. However, the specifics on how individual components should be developed are less clear, I have found using the following worked well on the most recent projects I have been working on.

The general architecture is shown in the component architecture diagram. For every component that you might create, you actually create two components. These components divide the responsibility between the visual/interactive elements and communication with external services, for example, a web server using HTTP.

In the figure, Component 1 is responsible for interaction with the server (getting, updating and deleting data) component 2 handles the displaying of any data and how to deal with user interactions. Component 1 passes data to component 2 using Angular @Input properties, binding the values. Component 2, uses @Output properties to raise events in component 1 to send information back to the server.

Components within the overall project are grouped under feature folder representing areas of the overall application. Within feature folders there are two folders that hold components: a ‘container’ folder (containing the visual and interactive components) and a ‘container’ folder (containing components that interact with servers). Each feature folder represents a separate module within the Angular application, designing components this way can allow modules to be lazy loaded, potentially improving performance.

Example: Project list view, adding a new project

In this example, we will look at how this approach is used to display and interact with the project lists within the TestDo application (https://github.com/JonathanSiddle/TestDoServer).

Rendered Angular Component

The browser screenshot shows an overview of the displayed project list component, the entire component is wrapped in a `HomePageComponent` which handles the displaying of the sidebar and toolbar, with routed components rendering in the main area of the page underneath the toolbar. The `TodoProjectListComponent` does not containing any visual elements, the template only consists of rendering the `TodoProjectListViewComponent` and binding values.

TodoProjectList.html

The snippet above shows the template for the `TodoProjectListComponent`, as can be seen, it simply displays the `TodoProjectListViewComponent` and sets up bindings for project data and events for adding, editing and deleting projects. A snippet of code form `TodoProjectListViewComponent` highlighting the code that will raise an event to add a new project is shown below. The component handles the displaying of a dialog that allows users to enter data and make sure this is valid, if it is an event will be raised in the `TodoProjectListComponent` to add a new project with the given name.

ToDOProjectListViewComponent.ts

Once an event fires the bound method in `TodoProjectListComponent` will handle the next stage. The job of this method is to simply to create a new `ToDoProject` object and send this to the server. If the result is successful the returned object (which will have a unique identifier) is added to the project list, which will then update the underlying visual representation due to data binding. Errors sending data can also be handled here, right now the error is just output to the console.

Final thoughts

While this approach may seem overly verbose it allows the interaction with the server to be tested completely independent of underlying view. It also allows the visual elements to be further separated into sub components if they are particularly complex, and to be tested simply by manually setting their data properties. I will look at how I developed unit tests for these components in another blog post!

--

--

Jonathan Siddle

Hey, I’m Jonathan! I make software, I write things and occasionally speak in front of people. I currently working mostly on Flutter applications.