Confirmation Dialogs
The Hyvä confirmation dialogs are built on top of the modal dialogs. All methods from the Modal ViewModel API Reference are available in addition to the confirmation-specific ones below.
Available since Hyvä 1.1.13
To create a confirmation dialog instance, use the confirm method on the modal view model:
use Hyva\Theme\ViewModel\Modal;
/** @var Modal $modalViewModel */
$confirmation = $modalViewModel->confirm(__('Are you sure?'));
The default confirmation template is Hyva_Theme::modal/confirmation.phtml.
Configuration
Content
withTitle(string $title)
Set the dialog title. This is the same as passing it directly to confirm('the title'). The title is escaped during rendering.
withDetails(string $details)
Add detail text rendered between the title and the buttons. The value is not escaped and may contain HTML.
Example:
withContent() vs. withDetails()
Confirmation dialogs also inherit withContent() from the base modal. If withContent() is set, the default template is bypassed entirely and no title or buttons are rendered. Use withDetails() to add body text while keeping the standard confirmation layout.
Button Labels
| Method | Description |
|---|---|
withOKLabel(string $label) |
Override the confirm button label. Default: OK. |
withCancelLabel(string $label) |
Override the cancel button label. Default: Cancel. |
Example:
Template
withTemplate(string $template)
Override the default confirmation template for this specific dialog.
Example:
Triggering actions
The show() method on the PHP view model returns a JavaScript promise that resolves when the user makes a choice. Chain .then() to handle the result: true means confirmed, false means cancelled.
Example:
<button
type="button"
class="btn"
@click="<?= $escaper->escapeHtmlAttr($confirmation->getShowJs()) ?>.then(result => result && doSomething())"
>
<?= $escaper->escapeHtml(__('Delete')) ?>
</button>
<?= $confirmation ?>
Dialogs with more than two choices
Pass a distinct value to hide() from each button in a custom template to build a dialog with more than two outcomes. The show() promise resolves to whatever value is passed to hide().
Example:
<button @click="hide('a')" type="button" class="btn">
<?= $escaper->escapeHtml(__('Option A')) ?>
</button>
<button @click="hide('b')" type="button" class="btn">
<?= $escaper->escapeHtml(__('Option B')) ?>
</button>
<button @click="hide('c')" type="button" class="btn btn-primary">
<?= $escaper->escapeHtml(__('Option C')) ?>
</button>
Alpine.js (without PHP)
Using x-htmldialog, a confirmation dialog can be built with a small Alpine component that exposes a promise-based confirm() method, matching the feel of the PHP view model approach:
<script>
document.addEventListener('alpine:init', () => {
Alpine.data('confirmDialog', () => ({
open: false,
resolve: null,
show() {
this.confirm().then(result => {
// handle result here
console.log(result);
});
},
confirm() {
return new Promise(resolve => {
this.resolve = resolve;
this.open = true;
});
},
ok() {
this.open = false;
this.resolve(true);
},
cancel() {
this.open = false;
this.resolve(false);
}
}));
});
</script>
<div x-data="confirmDialog">
<button type="button" class="btn" @click="show">Show</button>
<dialog
x-show="open"
x-htmldialog.closeby.none
aria-labelledby="the-label"
>
<div id="the-label">Are you sure?</div>
<div>Think before you click...</div>
<div class="mt-6 flex justify-between gap-2">
<button @click="cancel" type="button" class="btn">Cancel</button>
<button @click="ok" type="button" class="btn btn-primary">OK</button>
</div>
</dialog>
</div>
By default this example uses x-htmldialog.closeby.none to force an explicit choice. If you want ESC or a backdrop click to count as a cancel, replace it with x-htmldialog="cancel" and the promise will still always resolve.
Examples
Confirmation dialog with only details
$confirmation = $modalViewModel->confirm()
->withDetails($escaper->escapeHtml(__('Are you sure?')));
Confirmation dialog with title and details
$confirmation = $modalViewModel->confirm(__('Are you sure?'))
->withDetails('<em>Think before clicking.</em>');