Skip to content

Bridges ​

The bundle shares any page's pointers and presence, and any form's draft, through markup of its own (data-collaborate-*). A bridge is what it knows of an admin beyond that:

  • the services that say which record a form edits and when it is saved;
  • the regions a pointer is placed from (cursors.regions);
  • the script profile that reads the admin's markup: its rows and collection items, the page a list or record is shown on, its embedded lists, its row selection, its overlays, its collection and slug widgets, and its save buttons.
BridgeAdminSelected by
noneAny Symfony page: your controllers, your form contextcollaborate.bridge: none, or auto without EasyAdmin
easyadminEasyAdmin 4.24+ or 5collaborate.bridge: easyadmin, or auto with EasyAdminBundle registered
drupalDrupal 11.3+ or 12, on Claro or GinInstalling the janalis/collaborate_drupal module

Choosing the bridge ​

yaml
# config/packages/collaborate.yaml
collaborate:
    bridge: auto   # the default: easyadmin when EasyAdminBundle is registered, none otherwise

auto reads the bundles the kernel registers: EasyAdmin installed as a dependency of another package does not select its bridge. Set none to leave EasyAdmin's adapter out of an application that registers EasyAdmin for other pages. Setting easyadmin without EasyAdminBundle registered stops the container from compiling. drupal is refused: Drupal does not boot the bundle, its module builds the services itself.

The resolved bridge is the collaborate.bridge parameter, and the layer tells it to the page's scripts (data-config).

What each bridge brings ​

noneeasyadmindrupal
Form contextYours (No bridge)EasyAdminFormContextThe module's entity forms
Save hookYour controller calls DraftSave::completed()SaveSubscriberThe module's submit handler
Default regionsmodal, header, content, bodymodal, header, mobile-header, sidebar, content, bodymodal, header, sidebar, content, body
Rows, entriesdata-collaborate-row, data-collaborate-entryand .form-group, .field-collection-itemand Form API's .js-form-item, multi-value table rows
Saved-view refreshPages marked data-collaborate-pageand EasyAdmin's index and detail pages, embedded listsContent listings, views, entity pages
Script entrycollaborate.jseasyadmin.jsThe module's

The regions of each bridge, as the configuration reference lists them:

yaml
# none
modal: 'dialog[open], .modal.show'
header: 'body > header, [role=banner]'
content: 'main, [role=main]'
body: body
# easyadmin
modal: .modal.show
header: .content-top
mobile-header: .responsive-header
sidebar: '.ea-sidebar, .sidebar'
content: .content-wrapper
body: body
# drupal (Claro, Gin)
modal: .ui-dialog
header: '#toolbar-bar, .gin-secondary-toolbar, .region-header'
sidebar: '.layout-region--secondary, .gin-sidebar'
content: '.region-content, .layout-region--main, main'
body: body

cursors.regions replaces them; leave it empty for the bridge's.

The script entries ​

Import one entry per page, before anything that wraps window.fetch:

js
import '@janalis/collaborate/collaborate.js'; // no bridge, or whichever the layer names
import '@janalis/collaborate/easyadmin.js';   // EasyAdmin's profile, then every module

Each entry starts the cursors, the saved-view refresh and the shared drafts, and exports sessionFor(), addRowInitializer() and registerBridge(). The layer names the bridge the server resolved; when its profile is registered, the scripts read the page with it, else with the profile the entry registered, else with no bridge's.

An admin of your own can describe its markup the same way:

js
import { registerBridge } from '@janalis/collaborate/bridge.js';

registerBridge({
  name: 'none', // the layer's bridge whose profile this replaces
  rows: ['.my-field'],
  entries: ['.my-collection-item'],
  selection: 'input.row-select',
  submitters: ['save'],
});
import '@janalis/collaborate/collaborate.js';

Marking a page ​

The saved-view refresh reloads a list or a record's detail page when a save elsewhere changes what it shows. A page says what it shows on its body:

html
<body data-collaborate-page="Article:index"> <!-- a list of articles -->
<body data-collaborate-page="Article:detail"> <!-- one article -->
<body data-collaborate-page="index">          <!-- a list, refreshed for any save -->

The entity name is the short class name the bundle announces (Article for App\Entity\Article); under Drupal, the entity type (node). The kinds edit and new mark forms, which follow their draft instead. EasyAdmin's pages are read from their body classes; Drupal's are marked by the module.

Released under the MIT License.