Skip to content

📚 pbMessage — Universal Message Display

pbMessage is a small, general-purpose class that displays success or error messages after pbFetch requests or any async operations of your own. It also handles the confirmation dialog shown before a request.

✅ Why Use It?

  • Lets you automatically display messages from JSON responses like { success: true|false, message: "..." }.
  • Works out of the box together with pbFetch — no manual handling required.
  • Controlled via the custom pb:success and pb:error events — you can cancel the automatic display.
  • Gives you a single place to change how messages look across the whole site: plug in your own handler and plain text inside a block becomes toasts or modals.
  • Makes it easy to configure the CSS classes, where the message is inserted, and how it is cleared.

⚙️ How It Works

🚦 Core Logic

js
pbMessage.success(ctx, message)
pbMessage.error(ctx, message)
pbMessage.clear(ctx)
  • ctx is a DOM element inside which the output container is looked up. Usually it's a form or the element from pb-target.
  • pbMessage.success() looks for [pb-success-message], and falls back to [pb-message] if it isn't found.
  • pbMessage.error() looks for [pb-error-message], and falls back to the same [pb-message].
  • If no container is found, nothing happens.

ctx is required, and it fails silently

All three methods simply return when ctx is empty: no message, no console error. This is exactly what the most common "pbMessage doesn't work" looks like — there is nowhere to put the message. pbFetch uses the element's form as the context, and if there is no form, the element from pb-target; when there is neither, ctx is null.

🏷️ HTML Markup

1️⃣ A single universal container

html
<div pb-message class="d-none"></div>

2️⃣ Separate containers for success and error

html
<div pb-success-message class="d-none"></div>
<div pb-error-message class="d-none"></div>

✔️ It's best to place these containers inside the form or inside the target, so that pbMessage is sure to find them by context.

📌 Form Markup Example

html
<form id="my-form">
	<input type="text" name="name">
	<button
		type="submit"
		pb-post="/api/submit"
		pb-expect="json"
		pb-include="#my-form input"
	>
		Submit
	</button>

	<!-- Better inside the form -->
	<p pb-success-message class="text-success d-none"></p>
	<p pb-error-message class="text-danger d-none"></p>
</form>

The text is inserted via innerHTML — the server can send simple markup (<b>, <a>) right inside message. Which also means escaping user input is the server's job.

🧩 Auto-Integration with pbFetch

A message is displayed when three conditions are met:

  1. the request was made with pb-expect="json" (there are no messages at all for html);
  2. the response contains a non-empty data.message;
  3. the corresponding event was not cancelled.
js
// on response.ok
pbMessage.success(ctx, data.message)

// on an HTTP error
pbMessage.error(ctx, data.message)

You can cancel the automatic display by adding this to your handler:

js
document.addEventListener('pb:success', (e) => {
    e.preventDefault(); // the message won't be shown automatically
    // your logic
});

preventDefault() on pb:success disables more than just the message

On a successful response this event guards the entire JSON handling: the message, the redirect via data.redirect, and the markup replacement from data.html. By cancelling the message you take on the rest as well. On pb:error only the message is cancelled.

❓ Action Confirmation

The pb-confirm attribute of pbFetch calls pbMessage.confirmHandler(el, message) and sends the request only if it returned a truthy value:

html
<button pb-delete="/cargo/12" pb-expect="json" pb-confirm="Delete the order?">
  Delete
</button>

The default handler is the browser's confirm(). Here's how to replace it with your own:

js
pbMessage.setConfirmHandler(async (el, message) => {
    const result = await Swal.fire({
        title: message,
        icon: 'question',
        showCancelButton: true,
        confirmButtonText: 'Yes, delete it'
    });
    return result.isConfirmed;
});

The handler may be async — it will be awaited. It must return true for the request to go out; an exception thrown inside the handler cancels the request and is logged to the console.

🎨 Configuring Classes via Config and System Settings

By default the message classes come from system settings:

  • pageblocks_msg_success — classes for a success message
  • pageblocks_msg_error — classes for errors
  • pageblocks_hidden_class — the class that hides the message container (for example, d-none)

Sample setting values:

plaintext
pageblocks_msg_success = "text-success"
pageblocks_msg_error = "text-danger,text-error"
pageblocks_hidden_class = "d-none"

They are applied not by the pb.message.v300.js file itself, but by the component: with the pageblocks_load_scripts setting enabled, the OnWebPageInit event appends a setConfig() call with these values to the page. The class itself only hardcodes the fallbacks:

js
pbMessage.config = {
  successClasses: ['text-success'],
  errorClasses: ['text-error', 'text-danger'],
  hiddenClass: 'd-none'
};

The classes are Bootstrap ones; PageBlocks ships no styles of its own for them. On a theme without Bootstrap, set your own values in the settings.

You can also override them manually via setConfig():

js
pbMessage.setConfig({
  successClasses: ['alert', 'alert-success'],
  errorClasses: ['alert', 'alert-danger'],
  hiddenClass: 'hidden' // a TailwindCSS class, for example
});

When showing a message, pbMessage removes the hidden class and the classes of the opposite type, then adds the required ones. That's why a single [pb-message] container switches happily from error to success and back.

🧹 Clearing Messages

If you need to remove a message and reset the classes:

js
pbMessage.clear(form);
// or pbMessage.clear(targetElement);

The method walks all three attributes — [pb-success-message], [pb-error-message], [pb-message] — clears the text, puts the hidden class back, and removes the success and error classes.

🔥 Full API

MethodDescription
pbMessage.success(ctx, message)Show a success message
pbMessage.error(ctx, message)Show an error
pbMessage.clear(ctx)Clear all messages and reset the added classes
pbMessage.setSuccessHandler(fn)Override the success handler
pbMessage.setErrorHandler(fn)Override the error handler
pbMessage.setConfirmHandler(fn)Override the confirmation dialog (pb-confirm)
pbMessage.setConfig({...})Set the CSS classes for success/error (class arrays)

All three set*Handler() methods throw a TypeError if you pass anything other than a function.

✔️ SweetAlert2 Integration

js
pbMessage.setSuccessHandler((ctx, message) => {
    Swal.fire({
        icon: 'success',
        title: 'Success!',
        text: message
    });
});

pbMessage.setErrorHandler((ctx, message) => {
    Swal.fire({
        icon: 'error',
        title: 'Error!',
        text: message
    });
});

Your own handler is free to ignore ctx entirely — toasts and modals live on top of the page, and that makes the "there is no message container in the context" problem disappear.

© PageBlocks 2019-present