Skip to content

feat: MCD-1386 Route the message AJAX command into the global messages. - #532

Closed
drubot wants to merge 4 commits into
2.xfrom
feature/MCD-1377-ajax-messages
Closed

feat: MCD-1386 Route the message AJAX command into the global messages.#532
drubot wants to merge 4 commits into
2.xfrom
feature/MCD-1377-ajax-messages

Conversation

@drubot

@drubot drubot commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

Delivers Drupal messenger messages carried in AJAX responses (e.g. a webform managed_file upload error) into the decoupled frontend's global messages, as structured data.

This is the frontend half of MCD-1386; it lets MCD-1377 work end-to-end. The backend half is a core patch (ManagedFile::uploadAjaxCallback emits typed MessageCommands instead of rendering status_messages into the widget #prefix) — see #3457067; mossbo ships it via composer until it lands.

What this does

Registers a handler for Drupal's message AJAX command (core's MessageCommand). Core's own handler renders through Drupal.Message into a theme's [data-drupal-messages] region — a decoupled page has neither that region nor core's message CSS — so the payload is routed into the module's existing global messages instead:

  • The handler lives in useDrupalCe next to getMessages() and pushes a DrupalMessage straight into that state — no separate sink/registration layer. It is installed once, over Drupal.AjaxCommands.prototype.message, right after the AJAX library loads.
  • Type mapping: error and warning kept; status/unknown → success.
  • clearPrevious resets the message state first, so a retried upload replaces its earlier error instead of stacking duplicates.
  • A general Drupal AJAX feature — not tied to managed_file. The insert command is never touched (no HTML parsing anywhere).

Type

A single DrupalMessage type ({ type: 'error' | 'warning' | 'success', message }) in types.d.ts, reused by getMessages(), pushMessagesToState (the fetched page object's messages) and the menu error handler.

Verification

  • Full vitest suite 162/162 green, eslint clean.
  • installDrupalMessageCommand unit tests cover: routing into the global messages, type mapping, clearPrevious, no-op before Drupal.AjaxCommands exists, and install-once.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Tjk2QnTs86cpmMqAT57NGH

A webform managed_file upload error arrives inline: core's
ManagedFile::uploadAjaxCallback prepends #type => status_messages into
the replaced element's #prefix, so the messenger block renders inside
the widget — unstyled on the decoupled frontend, which never loads
core's messages CSS.

Wrap Drupal.AjaxCommands.insert to lift those .messages blocks into the
frontend's global messages (useDrupalCe().getMessages()) and strip them
from the inline HTML; wrap .message likewise. Field-level inline errors
(.form-item--error-message) stay next to their field.
}

/** A message forwarded from a Drupal AJAX response to the frontend. */
export interface DrupalForwardedMessage {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should define this is a general DrupalMessage type and use it here + elsewhere where it is used. let'S fix that.

* (`useDrupalCe().getMessages()`). Registered once via {@link setMessageSink};
* a no-op until then.
*/
let messageSink: ((messages: DrupalForwardedMessage[]) => void) | null = null

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nope, our module comes with the sink, it should jsut use that. --> the messages of the fetched page obect and getMessage of use DrupalCe

* Extracts Drupal messenger messages from an AJAX response's HTML, forwards
* them to the registered sink, and returns the HTML with those blocks removed.
*
* Drupal's managed_file upload AJAX callback prepends `#type => status_messages`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a general Drupal ajax feature, not limited to managed_file

* Drupal's managed_file upload AJAX callback prepends `#type => status_messages`
* into the replaced element's `#prefix` (see
* \Drupal\file\Element\ManagedFile::uploadAjaxCallback), so upload errors arrive
* as a `.messages` block inside the inserted markup — unstyled on the decoupled

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make comment more brief and structured

*
* No-op until `core/drupal.ajax` has defined `Drupal.AjaxCommands`.
*/
function installAjaxMessageForwarding(): void {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should go away

@drubot drubot changed the title fix: MCD-1377 Route AJAX response messages to the global messages. feat: MCD-1386 Route the message AJAX command into the global messages. Aug 19, 2026
…nk indirection.

Address review on #532:
- Define a general DrupalMessage type (types.d.ts) and reuse it for
  getMessages(), pushMessagesToState and the menu error handler.
- Remove the loader-side message sink (setMessageSink/messageSink):
  the module already owns the sink via getMessages(). The message
  command handler now lives in useDrupalCe and pushes into that state
  directly, installed once after the AJAX library loads.
- The handler is a general Drupal AJAX feature, not managed_file
  specific; comments trimmed accordingly.
@drubot

drubot commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator Author

🤖 Claude Code: addressed the review (head 365c09a).

  • General message type (r3814073044): added DrupalMessage to types.d.ts and reused it for getMessages(), pushMessagesToState (the fetched page object's messages) and the menu error handler. The local DrupalForwardedMessage is gone.
  • Use the module's own sink (r3814084109) + "remove this weird message-sync": dropped setMessageSink/messageSink entirely. The message command handler now lives in useDrupalCe and pushes straight into getMessages(), installed once after the AJAX library loads. The loader is back to pure script-loading.
  • General AJAX feature, not managed_file (r3814087010) + brief comments (r3814089348): the remaining doc comment describes the general message command; trimmed.
  • Scraping should go away (r3814096510): already removed in the earlier rework; insert is untouched.

PR description updated. Suite 162/162 green, eslint clean. The kickstart patch (nuxtjs-drupal-ce+2.8.0.patch, PR #1387) is resynced from this head so the LDP CI integration test runs the reworked frontend.

useState is unreliable after an await (Nuxt instance may be lost), so
getMessages() moves ahead of the dynamic import; only the AjaxCommands
install (window-only) stays after the library loads. Without this the
message command handler could silently fail to install.
@drunomics drunomics deleted a comment from drubot Aug 20, 2026
@fago

fago commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

figured there is already a drupal ajax message command which does the job well, I added as https://www.drupal.org/project/drupal/issues/3618230#comment-16740311 for handling file upoads nicely.

@fago fago closed this Aug 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants