The concept of UI Composition has been around for a while. The general notion is to break up bits of content and features into components that can be assembled together on a web page. Microsoft Blazor takes advantage of Razor Components. This is great because it gives you a great deal of flexibility in deciding what bits of HTML and/or C# you want to include in a component and you can even take it a step further with Razor Class Libraries which will allow you to bundle all sorts of things together to represent those building blocks for your web page.
This article helps to answer the following topics:
- What is UI composition?
- What are components?
- The importance of component communication.
- Working example using the BlazorComponentBus Nuget package
How does a Composite UI work?
Consider an item for sale at Amazon. Several parts of the screen are responsible for different pieces of data and functionality. They can (and should) be separate components that are responsible for themselves, their data, what they display, and what they do. Below is the .NET DevOps for Azure book by Jeffrey Palermo. Each highlighted section of the screen represents a different component:
In this example we can see how these various chunks or sections of the page could be broken up into components. We can see that there is pricing info, more buying choices, product info, ratings, buy now buttons, and more. While all of these things have a lot in common and are related, they are still very different bits of data and functionality. By isolating these things into components, we now have the ability to make them independent of each other and highly decoupled. So much so that they can even be responsible for reaching out to their own API endpoints to manage their data. The ability for components to be self-contained in such a way makes it possible to expand your composite UI into the realm of Micro Frontends. The concept of Micro Frontends came around as a means to figure out how to extend the microservices architecture into the UI and with Microsoft Blazor and Razor Components this can now be achieved.
In recap a composite UI is the assembly of various components on a web page to create a highly decoupled and feature rich visual interface. Extending the components to encapsulate the management of their own data opens the door for building Micro Frontends. However, to be successful, we still need to implement some best practices to ensure that this frontend architectural pattern doesn’t begin to deteriorate in the long run.
It’s necessary to be thoughtful when creating the composition of a web page using components because things can easily turn into a ball of mud if you are not careful. It’s desirable to prevent Razor Components and Razor Class libraries from taking dependencies on each other to avoid coupling. For example—button clicks and mouseovers in component A should not directly affect or make things happen in component B. In other words, A should not be telling B what to go do with itself. If A knows about the inner workings of B then we have a tightly coupled set of components. So how do we prevent this?
The answer is by introducing component messaging. Messaging allows for Razor Cmponents to communicate without having dependencies on each other. It’s similar to the concept of posting a message on your social media account. Once you post your message others can choose to read it, troll you, give it a thumbs up, unfriend you, or ignore it completely.
Blazor .NET Event Messaging
The idea of component messaging is to create a way for components to interact without the need for tight coupling in our code.
When an action occurs, a component can emit a message that other components can listen for. When a listening component receives a notification that the action has occurred it can then decide how to act upon that knowledge. This action is referred to as an event.
The term event can be a bit overloaded at times. In the world of messaging there are two kinds of messages—commands and events. Commands are one to one. Events are one to many. Events make the most sense in a loosely coupled system because a component can publish an event message without knowing or caring about what other components may be listening for it. Commands require a component to know and be aware of another component. To send a command you must know who or what you are sending it to.
The term event is also used when referring to things that happen within a web browser such as mouse over, key press, or click event. Often times you will combine a “browser event” with sending an “event message.” For example, a button click in your Razor Component can trigger the execution of code that publishes an event message.
Out of the box Blazor does not have the capability for sending messages between components, however, enabling this functionality is easy enough in Server Side Blazor applications. Simply add the BlazorComponentBus Nuget package to your projects.
Example Composite UI with BlazorComponentBus
In this example we are using the domain of Hogwarts school of Witchcraft and Wizardry to demonstrate component messaging in Blazor.
With the defeat of Lord Voldemort there has been a huge spike in school enrollment requests at Hogwarts and there just aren’t enough owls to deliver acceptance letters. So, the ministry of magic has set aside a budget for developing an online enrollment system to skip through the onboarding of students and getting them sorted directly into their school houses.
For this composite UI example we are using a Blazor .NET SPA application which consists of 3 components:
- AddStudents Component
- HouseAssignments Component
- SortStudentsToHouse Component
The process begins by entering a new student’s information. The AddStudent component emits an event message notifying the other components on the page that a student has been added to the system. The HouseAssignments component adds the students name to the list while the SortStudentToHouse component asynchronously begins the process of sorting the student. Once the student has been assigned to a house a HosueAssigned event message is fired off and picked up by the HouseAssignments component which updates the student list to also display the house they have been assigned to. Below is a diagram which shows the flow of events: