Conduits provide a simple way of allowing multiple components to share data and remain in sync with minimal setup. It also provides simple control mechanisms to define how data is shared between components through zones.
A conduit is built on top of the RxJS Subject. To create a conduit you should create
a public instance variable on your component class. This should be initialized as a new
Subject or BehaviorSubject if you want to specify a default value.
When a conduit is created, for example when a component is initialized, it will check if there are any other conduits with the same id in accessible zones and if so will retrieve the latest value. This is useful in scenarios such as a customizable dashboard where widgets may be dynamically added or removed. When a dashboard widget is added it can automatically detect a value to consume from any other widgets with a matching conduit.
The variable should be given the @Conduit decorator with the appropriate
configuration. Additionally the component class should extend ConduitComponent where
possible to setup all conduits automatically. If it is not possible to extend this class, inject
the ConduitZone service and in the ngOnInit hook call
zone.registerConduits(this). In the ngOnDestroy hook call
zone.unregisterConduits(this) to remove conduits when they are no longer needed.
Below is an example of creating a conduit:
The following properties can be given to the Conduit decorator:
id
will be kept in sync if they accept input.
false
then it will not update when other conduits with the same
id
change. If this property is set to
true
then it will always update when other conduits with the same
id
change. Alternatively this can be set to a string array of zone ids. If a conduit with the same
id changes in one of the specified zones then it will update, otherwise it will not.
false
then it will not emit this change to any other conduit. If this property is set to
true
then it will emit this change to other conduits.
===
comparison, however if the conduit value is an object or an array you may need to provide a
custom equality check to ensure equality check is efficient and to prevent any infinite loops.
The value should be a simple function that receives two arguments, the new value and old value.
The function should return
true
if the object are the same and
false
if it has changed.
User
conduit that contains an object. In one component we may want only to receive the name of the
user. We can use this property to provide a function that takes in the conduit value and returns
it in a format we require.
By having our component extend the ConduitComponent we gain access to some utility
functions that can be used to create and modify conduits dynamically at runtime.
The following methods are available:
This allows programmatic creation of a conduit at runtime. The function should be called with
two parameters, the first is the Subject or BehaviorSubject, and the
second is the properties object which is identical to the object normally passed to the
@Conduit decorator.
Note: If your class does not extend ConduitComponent, these functions are
also available on the ConduitZone service.
This allows conduit properties to be modified at any time. For example, you may wish to alter
which zones a Conduit can accept data from. This function should be given two arguments. The
first argument should be the Subject or BehaviorSubject, the second
should be an object containing the properties you wish to update.
Note: If your class does not extend ConduitComponent, these functions are
also available on the ConduitZone service.
A conduit zone is a way of easily scoping what conduits can be effected when values change.
To create a conduit zone a component should register the ConduitZone provider and
where possible extend the ConduitZoneComponent class. The
ConduitZoneComponent class extends ConduitComponent so you also have
access to the methods listed above. Each zone must also have a unique id which should be set by
adding a zoneId property to the class.
If a class extends ConduitZoneComponent and uses the ngOnInit or
ngOnDestroy lifecycle hook, you must call super.ngOnInit() and
super.ngOnDestroy from within the respective hook.
If it is not possible to extend the ConduitZoneComponent class, you should inject the
ConduitZone service and call the setZoneId function passing it the
unique zone id.
Below is an example of how to create a zone:
Conduit zones work with Angular's Injector, so a conduit created in the component, or
a child component will be part of that zone. Zones may be nested, so a child component may create
a new zone.
The following code can be used to create the example above: