Thursday, January 30, 2020

Using Interfaces To Communicate Between Components and Pages



Issue #1

Parent / Child Communication With Interfaces

When I built my BlazorStyled Video, I discovered a neat way for components to communicate with their parent component or page by using Interfaces.

Since then I realized I didn't want to create interfaces for each component, so I created two generic interfaces to handle this:

    * View the source code on GitHub

* The code above is part of the open source project and Nuget package: DataJuggler.Blazor.Components, a work in progress.

In the diagram for the sample project below, the Index page contains a component named Login, and the Login component has a child component named SignUp.


The Login component has an EventCallback parameter:








In this scenario I am building a sample called Blazor Image Gallery where artists can sign up and upload images for their own portfolio as part of the Gallery.

My database contains an Artist table and when a user signs up or logs in, I needed a way to inform the Index page that a user (an Artist) has signed in.

One option is to set a Parameter on the Index page for Artist ID or I could use the Preview Nuget package Microsoft.AspNetCore.ProtectedBrowserStorage, which this project already uses to store the users email address and password hash if a user chooses to be remembered. I didn't like either of these options because I still needed a way to send messages to the parent component or page. 

Interfaces
Interfaces make communication between a parent page or component and child very simple. In this example my Index page and Login component both implement IBlazorComponentParent and the Login and SignUp components both implement IBlazorComponent.



Both the IBlazorComponent and IBlazorComponentParent interfaces have a ReceiveData method:











In the image below, the Login component implements IBlazorComponentParent interface, so setting the parent is as simple as Parent = "this":

The SignUp component implements IBlazorComponent, and your setter for the Parent property needs to look something like this:



In the above setter, the HasParent property is a simple test for (Parent != null).

If the Parent exists, the SignUp component registers itself with the parent Login component.

Registering Components

Objects that implement IBlazorComponentParent must contain a Register method. The Register method will be called the first time the Parent property is set. This usually occurs when a component is rendered for the first time.

IBlazorComponentParent objects contain a property named Children that you may instantiate to store child components as they register. You can also store component instances as a property, as shown here the Login component is expecting the SignUp component to register.




















In the picture above, NullHelper is part of DataJuggler.UltimateHelper.Core Nuget package, and it a shortcut for (component != null) && (Children != null).
Once both objects are verified to exist, the component is added to the Children collection.

Sending Messages

A message object is a class that contains a few properties to make it easy to send information between components.

Message Objects

Text - A string property for any text information you want to send.

For more complex data, I created an object called a NamedParameter.

NamedParameter Properties:

    Name - An identifier so parameters can be set to distinguish items
    Value - An object value that can contain any type of data.

Each message contains a Parameters collection that is created when you call the constructor for a Message.

At some point a MessageHelper class will be created to simplify this, but for now create your NamedParameter instances and add them to your message.

In the example shown below, the SignUp component is notifying the Login component that an Artist has signed up:
























In the Login component I receive the message, then I call the OnLogin EventCallback which notifies the Index page.








































The Index page then receives the LoginResponse object, which I get the Artist from and store in memory:








































After login, my UI is updated and the Login Component changes:



The Blazor Image Gallery is almost finished, I just wanted to write this blog post as I think interfaces are the easiest way I have found for communicating between parent and child.

Let me know your thoughts or if you know of a better way to communicate between components.

Thanks for reading. Please visit my YouTube channel and subscribe as I make new videos as often as I can. 

Data Juggler YouTube Channel

Corby / aka Data Juggler