Listen for backend form submitting ajax request “onSave”
Pause ajax request
Get data from custom formWidget module, that returns Promise as data
Wait until promise completed
Push data to form
Resume ajax request, let it collect data from form and send to backend
I tried listening for ajax:before-request but it doesn’t allow to pause request or cancel it. ajax:request-start returns xhrRequest, but there is no option to pause it, only to duplicate cancel and create a new one with custom data.
There is should be more convenient event for this kind of tasks.
I’m making a formwidget that anyone can install from marketplace, so this is not an option.
Also, can’t do this, overriding controller handler from fromwidget seems like overkill to simple task. I just need to pause save request and resume it when Promise from formwidget is done.
Also, worth pointing out. Backend can have multiple formwidgets, we don’t know the name of the fields, so overriding onSave handler is not an option…
The confirm-message event has a promise that works like you suggest:
$(window).on('ajax:confirm-message', function (event) {
event.preventDefault();
let promise = event.detail.promise;
// this would be a modal which the user can submit in our real world scenario.
setTimeout(function () {
$('#demo-field').val('some-value');
promise.resolve();
}, 5000);
return true;
});
There is also an example in the documentation that resubmits the request on the same element:
addEventListener('app:stale-document', function (event) {
if (confirm('Another user has updated this document, proceed?')) {
oc.request(event.target, 'onUpdate', { data: {
force: true
}});
}
});
Thanks for your suggestions, but they are wrong. Maybe I should clarify more what I’m trying to achieve.
I have a standard model form at the backend, with default field types, but only one or multiple has type “EditorJS”. The EditorJS is a WYSIWYG block-styled editor, and everything that is user doing with editor (typing, editing) is stored inside tab memory, but if you want to pull data out of EditorJS, you should call editorJs.save(). This method returns Promise that after completing gives you JSON data.
I want to put this JSON data inside the textarea of formwidget, and the trigger to start this process should be a standard onSave event that the user calls by clicking on “Save” button in the form.
So in my head it should work like this:
Listen for ajax events on page
If triggered event has onSave handler pause ajax event
Trigger all fields with editorJs type and initate save promise and put result of promise inside textarea of each widget
Resume ajax event, let it collect data inside form that already has editorjs data inside textarea.
This logic should work without user noticing anything, just slight longer standard saving process of model.
If you look at the dispatchChange() event on the editorjs docs - you can fire an event to let the editor know that a block has changed. You could then listen for this event and call the editorJs.save() method to populate the textarea whenever a block is changed.
So by the time you press the October save button your textarea will already contain it’s content.
User can press CTRL+S/CMD+S hotkey which immediately call onSave method.
This solves the problem only if contents of EditorJS are small and doesn’t have any “heavy” blocks that should do some work on saving. That’s why EditorJS returns Promise but not directly content, because if the developer has blocks that do some heavy work on saving (we also should consider this) your method will not work. Calling a million times editorjs.save() method is not a solution of a problem in my opinion.
Sure. I’m not a “pro” in JavaScript, but something like this:
const editorjs = EditorJS(...);
const textarea = document.querySelector('form > textarea');
// Event that should fire before everything (gathering data, crafting request and etc.)
// Because we want to put data inside form that should be send in request
addEventListener('ajax:before-everything', event => {
const { context } = event.details; // Get basic event information
// We want to call this custom logic only on `onSave` event
if (context.handler == 'onSave') {
editorjs.save().then(outputData => {
textarea.value = JSON.stringify(outputData);
event.release(); // Resume the event
}).catch(error => {
alert(error.message);
event.die(); // Kill the event if error occured
});
} else {
event.release(); // Resume the event if wrong handler
}
});