The dev panel

The dev panel is the in-browser editor. Two things set the V21 panel apart from what older notes describe: its fields are generated from the schemas, and it lives in a shadow root.

Fields are no longer hand-coded

DevPanelRenderer resolves the block's schema and renders one field per declared property:

  • control picks the widget;
  • section picks the accordion;
  • visibleWhen decides whether the field shows;
  • dependents says what gets re-rendered when it changes.

The practical consequence: to add a setting to a block, you edit its schema, not the panel. A forgotten dependents entry is the usual reason a field keeps showing a stale value after another one changed.

One way in for writing

Every change goes through a single entry point, WebFormController.setBlockPropertyV21:

{ uuidKey, property, value, … }

It resolves the schema, validates the value, routes it to the right place (properties, the CSS cube, an event, a style preset) and answers with the actions to replay. Rich text, Monaco and events included — nothing escapes it any more.

It writes into ds[GG_EDIT_CONTEXT], the table currently being edited.

Knowing which screen you are on

Three process variables carry the edit context:

VariableMeaning
GG_EDIT_CONTEXTThe table being edited — page content or template content
GG_IS_MODEL_EDITORThe template editor is open
GG_IN_MODEL_RENDERA template is being rendered inside a page

Trap: never identify the screen from WEB_vt_Url. Every panel action arrives on /bweb/call-action whatever the screen, so the URL tells you nothing — and splitting it into path segments raises an index error.

The shadow root changes the rules

The panel is mounted in a shadow root. Three habits break:

  • implicit globals are dead — a function declared in one panel script is invisible from another unless it is exported;
  • event-onClick attributes in markup never fire — attach listeners inside the shadow root;
  • document.querySelector does not reach panel nodes, and jQuery does not work there either.

And the mirror trap: the panel itself carries data-uuid attributes for the blocks it lists. An unscoped [data-uuid=…] selector aimed at the page also matches panel nodes — which has already destroyed the wrong element on a delete. Scope the selector, and quote and escape the value.

Styling inside the shadow root

output.css repaints every label and input of the panel. A rule written as #devPannel .x has lower specificity and loses on background, border and color (geometry still applies). Prefix with the tab's id and use !important for backgrounds.

Editors bundled by webpack (rich text, Monaco) mount but come out unstyled when style-loader injects into document.head instead of the shadow root. A webpack insert option handles this — recheck it after every rebuild, it has regressed more than once.

Access

The panel is served to a user allowed to edit the page. After a 4D restart the web session is lost and the panel disappears — log in again rather than hunting for a bug.

See also