@tao.js/react SwitchHandler Component
An additional React Component used to integrate the TAO with the components used to generate the
view of our React app is the SwitchHandler.
(all of the description below assumes a single Provider at the root of our React App)
(please see the Provider doc page for more about advanced usage)
The SwitchHandler is a React Component and a TAO handler attached to listen for AppCons
matching the configured Trigrams of its RenderHandler children.
Because the RenderHandler is designed to listen only for AppCons to which it is configured, it is
not aware of the other AppCons being set in the TAO. In order to control and determine when to
include or exclude individual RenderHandlers within a set that each attach to different Trigrams,
we surround them with a SwitchHandler.
importing
SwitchHandler is a named export from the @tao.js/react package.
import { SwitchHandler } from '@tao.js/react';
OR
const SwitchHandler = require('@tao.js/react').SwitchHandler;
Exclusivity Control of RenderHandlers
The SwitchHandler is different from the RenderHandler in that it does not take a function as a child
to define the TAO handler it uses to attach to the TAO. The SwitchHandler defines its own TAO
handler and attaches it for every Trigram it finds in direct child (no descendants are searched)
RenderHandlers.
…
import {
SwitchHandler,
RenderHandler,
} from '@tao.js/react';
import List from './List';
import View from './View';
import Form from './Form';
…
const SpaceContainer = props => (
{/* surround RenderHandlers with a SwitchHandler */}
<SwitchHandler>
<RenderHandler term="Space" action="List" orient="Portal">
{(tao, data) => <List data={data.Space} />}
</RenderHandler>
<RenderHandler term="Space" action="View" orient="Portal">
{(tao, data) => <View Space={data.Space} />}
</RenderHandler>
<RenderHandler term="Space" action="Edit" orient="Portal">
{() => <div>You must save for changes to take effect.</div>}
</RenderHandler>
<RenderHandler term="Space" action={['New', 'Edit']} orient="Portal">
{(tao, data) => <Form Space={data.Space} editing={tao.a === 'Edit'} />}
</RenderHandler>
<RenderHandler term="Space" action="View" orient="Portal">
{(tao, data) => <View Space={data.Space} />}
</RenderHandler>
</SwitchHandler>
);
export default SpaceContainer;
The example SwitchHandler above will attach its handler to the TAO for the following Trigrams:
{Space,List,Portal}{Space,View,Portal}{Space,Edit,Portal}{Space,New,Portal}
Convenience Trigram props
As we can see in the example above, many times several RenderHandlers will be grouped together
and use the same term, action and/or orient Trigram props in the case when we want to use
a SwitchHandler to decide which to render.
As a convenience, the SwitchHandler will accept term, action and/or orient props that will
be used as default values for its RenderHandler children. When doing this, the following 2
behaviors will occur from the SwitchHandler:
- the props will be combined with the same props from each child
RenderHandlerindividually, giving precedence to theRenderHandler's prop value, to determine the trigrams that theSwitchHandler's handler will be attached to the TAO - the props will be combined with the same props from each child
RenderHandlerindividually, giving precedence to theRenderHandler's prop value, to set the trigram props on theRenderHandlerthat is added to the component render tree so the actualRenderHandlers in the shadow DOM will have the same values used for attaching their TAO handler
We can modify the above example using this:
…
import {
SwitchHandler,
RenderHandler,
} from '@tao.js/react';
import List from './List';
import View from './View';
import Form from './Form';
…
const SpaceContainer = props => (
{/* use convenient default trigram prop values for term & orient */}
<SwitchHandler term="Space" orient="Portal">
{/* will receive term="Space" action="List" orient="Portal" props when rendered to the tree */}
<RenderHandler action="List">
{(tao, data) => <List data={data.Space} />}
</RenderHandler>
<RenderHandler action="View">
{(tao, data) => <View Space={data.Space} />}
</RenderHandler>
<RenderHandler action="Edit">
{() => <div>You must save for changes to take effect.</div>}
</RenderHandler>
<RenderHandler action={['New', 'Edit']}>
{(tao, data) => <Form Space={data.Space} editing={tao.a === 'Edit'} />}
</RenderHandler>
<RenderHandler action="View">
{(tao, data) => <View Space={data.Space} />}
</RenderHandler>
</SwitchHandler>
);
export default SpaceContainer;
Both above examples will have the exact same output where we have a more convenient and declaratively documented way to express our UI in the example directly above.
Overriding default trigram prop
If we further extend the example above to:
const SpaceContainer = props => (
{/* use convenient default trigram prop values for term & orient */}
<SwitchHandler term="Space" orient="Portal">
{/* will receive term="Space" action="List" orient="Reporting" props when rendered to the tree */}
<RenderHandler action="View" orient="Reporting">
{(tao, data) => <SpaceReport data={data.Space} />}
</RenderHandler>
<RenderHandler action="List">
{(tao, data) => <List data={data.Space} />}
</RenderHandler>
<RenderHandler action="View">
{(tao, data) => <View Space={data.Space} />}
</RenderHandler>
<RenderHandler action="Edit">
{() => <div>You must save for changes to take effect.</div>}
</RenderHandler>
<RenderHandler action={['New', 'Edit']}>
{(tao, data) => <Form Space={data.Space} editing={tao.a === 'Edit'} />}
</RenderHandler>
<RenderHandler action="View">
{(tao, data) => <View Space={data.Space} />}
</RenderHandler>
</SwitchHandler>
);
The RenderHandler that defines orient="Reporting" will have the orient value "Reporting" for
both the SwitchHandler trigram related to it and receiving props when added to the render tree.
Defining Multiple Trigrams
Just like with a standard TAO handler, it's possible to use wildcard definitions for the Trigram
of our SwitchHandler. This is done by either ommitting the Trigram prop for the desired wildcard
or by providing an empty string ("") as the prop value.
Additionally, as a convenience provided in the @tao.js/react package, all components can specify
multiple values for any Trigram prop to capture more than one specific AppCon (remember, a
wildcard will match any). This is done using an Array of values for the prop, e.g.:
<SwitchHandler term={['User', 'Role']} orient="Portal">
When a Trigram prop on a SwitchHandler has more than one value, after combining and overriding
trigram props from a child RenderHandler, the SwitchHandler will calculate the cartesian product
to determine all of the trigrams to which the SwitchHandler's handler should be attached.
If a child RenderHandler does not specify the trigram prop that is defined on the SwitchHandler
with multiple values then the RenderHandler will receive that prop with a definition of multiple
values thus the RenderHandler will perform the same cartesian product when determining trigrams
for its own handler as documented on the RenderHandler doc page.