This article also exists in: Italian

Communication between components and state management

In a previous article I talked about publisher/subscriber architecture for what concerns webcomponent, and the approach used in Maestrale for the management of communication between different web components in our industry’s 4.0 applications.

We also use Angular and React for projects of greater complexity and, although publisher/subscriber architecture and communication via EventBus is always a viable way to make components communicate with each other, adapting to the standards of frameworks or libraries we had to re-analyze the problem and use different approaches based on different use case of projects.

One of the most typical use cases, encountered almost daily, is when the components have ‘to dialogue’ not necessarily taking into account the hierarchically close relationship (parent -> child or child -> parent) but maintaining a generic common element that acts as a glue. In this case we speak of ‘sibling-relationship’.

Angular e Directive

In Angular we model this approach using as common component a Directive that acts as a ‘glue’ for all the components that, through dependency injection, obtain the use of the Directive itself.

In analogy with the webcomponent approach RxJS and the BehaviorSubject come to our aid.

We use the latter to maintain the application status (with private visibility within the Directive): the status update occurs by treating the BehaviourSubject [ref] as Observable and exposing it to components that need to get/update status.

Note that these components only have access to the BehaviorSubject (stream) Observable, not the BS itself!

Ultimately our Directive will deal with:

  • Maintain the state
  • Manage the status update via Observable (event stream [ref])

A practical example!

For our example, let’s use colors to describe the change of state: let’s imagine 2 components interacting by changing a series of HEX values that we use to display the background and foreground colors of the same. The state could therefore be represented by an object containing such values.

In our directive we instantiate and initialize the ‘state’ in the constructor through BehaviourSubject as Observable. Notice that we use a public ‘updateColor’ method that has access to the observable, then to the stream, to update the status.

private colorBS = new BehaviorSubject({});
public colorObservable$ = this.colorBS.asObservable();

constructor() {
    //default
    const def = new ColorObject();
    def.bkg = "#D1DB44";
    def.frg = "#8B0000";
    ...
    ...
    this.updateColor(def);
}

updateColor(color: ColorObject) {
    this.colorBS.next(color);
}

There are then 2 components.

color-bkg

Through the observable, the component takes care of showing the colors both in HEX and in RGB: in color$ I have the observable of the BehaviorSubject taken from the directive. I use the observable as an async stream to access the ‘state’ and then show it.

...
constructor(public directive: IntermediaryDirective) {}

ngOnInit() {
  this.color$ = this.directive.colorObservable$;
}
<div *ngIf="color$ | async as color" [ngStyle]="{'background': color.bkg}">
  <span [ngStyle]="{'color': color.frg}">Changed color text?</span>
</div>

color-picker

The component uses the observable to retrieve the ‘state’ and thus display the colors of the picker. In addition to this it calls the directive’s ‘updateColor’ method to update the state, and then notify the other components of the change (try to change color via picker!)

...
constructor(public directive: IntermediaryDirective) {}

ngOnInit() {
  this.color$ = this.directive.colorObservable$;
  ...
}
updateBackground(val) {
  this.objColor.bkg = val;
  ...
  this.directive.updateColor(this.objColor);
}
<ng-container *ngIf="color$ | async as color">
    <input
      #pickerbkg
      type="color"
      [value]="color.bkg"
      (change)="updateBackground(pickerbkg.value)"
    />
    ...
</ng-container>

To better verify the code and the example here is the playground!

Try to change color using the pickers: you will notice that both components are notified of the change of status by the Directive which they use as an ‘intermediary’.

There are many other methods to manage state and communication between different components in Angular but the BehaviorSubject is a common enough object to use in applications with responsive programming styles where we want some central state / information to be shared.

write forMaestrale IT

About the author

For the last 15 years, Stefano Frasca has worked with a variety of web technologies both backend and frontend. He is currently focused on front-end development. On his day to day job, he is working as a FullStack developer & Frontend dev fan at Immobiliare Labs IT. He has worked remotely for years, passionate about photography, food and code 😎
Do you want to know more? Visit my website!