Skip to content

Feature Demo: Toggling Pane Visibility

WindBeneathYourWings edited this page Mar 4, 2022 · 10 revisions
  • Contexts
    • State
  • Panel Visibility
    • Rules
  • External Communication
    • Bridge API

Demonstrates usage of panel page global state integration via contexts system. Also provides example of using bridge API to communicate with angular application via external JavaScript. The end result is a panel page with a link to reveal and hide content. This is meant to be a simple example that demonstrates using state and bridge. Other more complex examples to follow could be using these capabilities to temporarily display a pane while content is loading in another one. Once deployed to prod images will also have links to live page to try out for ones self.

Page Builder

Contexts

New context "hhhhhh" has been added.

The "hhhhhh" context uses the "State" context plugin. The state context plugin provides a text area for json. The json used here will act as the default state for the named context.

Content

The page has 3 panes. Each pane is a snippet. A snippet provides a textarea for HTML or Markdown. Custom JavaScript can also be used alongside the snippet.

The first snippet provides HTML for a paragraph that when clicked uses the the bridge to change the "hhhhh" state value for property displayPane to "y".

The second pane provides similar markup but changes the "hhhhh" state back to the default "n" displayPane value.

The last pane is a simple piece of content that will be revealed and hidden.

Without anything more this page would just display all three panes.

Rules

Rules can be added to panes to control their visibility. All contexts of a page are available to be used inside rules.

Using rules on the first pane when the "hhhhh" state displayPane value equals "n" the pane is displayed. Otherwise the pane is hidden.

The panes that follow use an inverse rule to control their visibility.

Now with the rules set up on the panes visibility of panes is dynamic triggered through changes in the "hhhhh" state context.

Page Render

Initial Page

The initial rendering of this page is below. Notice how only the clickable asset to reveal the hidden pane(s) is displayed at first. This is because the initial state of "hhhhh" displayPane is "n". The only pane that matches that rule is this very first pane.

Click

When the paragraph is clicked the other content is displayed instead.

Click Again

When the paragraph is clicked again the initial rendering is restored.

Redux

Context states are stored in the NgRx store using the data module. The actual name of entity in the store "GlobalState". The store is foundation that makes everything above possible. Contexts wrap around store changes to trigger repainting of page components that use a changed context.

Bridge

The API bridge is its own topic. In a nutshell though the API bridge allows developers to expose methods to the outside world that evaluate within the Angular context. Therefore, users can write plain javascript to interact with Angular application. This interaction is limited to API methods exposed on the bridge. The Bridge itself is plugin based and fully extensible without hacking at existing code.

Below is an example of how the bridge is extended inside the state module to allow writes. Bridge Builder is the plugin type that used to extend the bridge with functionality. The build() function contains the logic to extend the bridge via standard JavaScript prototype chain.

export const stateBridgeFactory = (es: EntityServices, attributeSerializer: AttributeSerializerService) => {
  return new BridgeBuilderPlugin<string>({
    id: 'state',
    title: 'State',
    build: () => {
      PublicApiBridgeService.prototype['writeState'] = (gs: GlobalState): Promise<GlobalState> => {
        return new Promise(res => {
          const svc = es.getEntityCollectionService('GlobalState');
          /*svc.getByKey(f.id).pipe(
            // catchError(() => of(new GlobalState({ id: f.id, value: attributeSerializer.serialize(f.state, 'root') }))),
            switchMap(state => svc.upsert(new GlobalState({ id: f.id, value: attributeSerializer.serialize(f.state, 'root') })))
          ).subscribe(state => {
            res(state);
          });*/
          svc.upsert(new GlobalState({ id: gs.id, value: attributeSerializer.serialize(gs.value, 'root') })).pipe(
            tap(state => res(state))
          ).subscribe();
        });
      }
    }
  }); 
};

The bridge is the back bone of communication between internal and external scripts. External scripts are anything NOT included as part of the Angular build but added at runtime instead.

Caveats

Snippet content MUST currently include a token for the context being used as part of a pane rule.

<span style="display: none;">[hhhhh.displayPane]</span>

This is necessary so that the discovery mechanism for contexts knows that the context is being used by the pane. Otherwise the context change detection cycle will not trigger. The cause of this is a gap in the context discovery logic for a panel. A gap that currently omits parsing rules for contexts that are used within panes for a panel.

Enhancements

Content pane states.

Content plugins will have state hoisted into the the scope of the containing pane. Users will be able to manipulate this state via a bridge method similar to how the state context. An example use case of this is providing asset loading progress for the media content pane. The media pane would expose state is manipulated within in the renderer so that users can create rules for for this state like hiding another pane with a throbber.

This feature was completed a while back and can in theory replace the original panel page form architecture.

Clone this wiki locally