Customizing Modal methods
Extend modal methods like show or hide to add custom logic. This can be done for individual modal instances or globally for all modals. The core principle remains consistent:
- Get the original method and store it in a reference variable
- Create a new function, that uses the reference to call the original function
- Add the custom logic to the new function
- Assign the new function in place of the original function
Customizing a modal method for a specific instance
To add custom logic to a specific modal instance's hide method:
<div x-data="{...hyva.modal(), init() {
const origHide = this.hide;
this.hide = (value) => {
// custom logic here
return origHide.call(this, value);
}
}}">
This example wraps the modal instance's hide method within the init function.
Customizing a modal method for all instances
To apply custom logic to *all* modal instances, two functions must be wrapped:
- The
hyva.modal()function is wrapped to return a modified modal instance - The target modal instance method is wrapped to run the custom code
The following example demonstrates wrapping the hide method for all modal instances. This code must render on the page **after** the original hyva.modal code, typically via the hyva_modal.xml layout file:
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceContainer name="before.body.end">
<block name="my-hyva-modal-patch" template="My_Module::modal-patch.phtml" after="-"/>
</referenceContainer>
</body>
</page>
The `after="-"` attribute ensures rendering after the original code.
Next, wrap the target method within the template:
<script>
(() => {
const originalModal = window.hyva.modal;
window.hyva.modal = function (options) {
const instance = originalModal(options);
const originalHide = instance.hide;
instance.hide = function(value) {
// custom code here
return originalHide.call(this, value);
}
return instance;
}
window.hyva.modal.eventListeners = originalModal.eventListeners;
window.hyva.modal.excludeSelectorsFromFocusTrap = originalModal.excludeSelectorsFromFocusTrap;
window.hyva.modal.pop = originalModal.pop;
})()
</script>
Note the explicit transfer of additional non-default properties (e.g., eventListeners, pop) to the new window.hyva.modal wrapper.
Using a JavaScript Proxy to wrap modal methods
While explicit references (e.g., const original = this.hide) are clear, JavaScript's Proxy class offers a more concise, implicit way to wrap methods. Proxies automatically preserve references to non-default properties (like eventListeners and pop), potentially simplifying the code, though familiarity with Proxies is beneficial.
This example achieves the same global hide method wrapping using JavaScript Proxies for both the hyva.modal function and the hide method.
// wrap hyva.modal function in a Proxy
window.hyva.modal = new Proxy(window.hyva.modal, {
// declare function interceptor on the proxy handler object
apply(target, objContext, args) {
// call original hyva.modal function
const instance = target.apply(objContext, args);
// wrap instance hide method in a Proxy
instance.hide = new Proxy(instance.hide, {
// declare function interceptor on the proxy handler object
apply(target, objContext, args) {
// custom code here
// call original hide function
return target.apply(objContext, args);
}
});
return instance;
}
});
Two distinct apply concepts are used in the above code:
target.apply(objContext, args)calls the original function usingFunction.prototype.apply.apply(target, objContext, args)declares a Proxy handlerapplymethod to intercept function calls on the original.
Refer to the MDN Proxy documentation for more details.