For passing the node ID to the controller use a route parameter:
The core example is in FileWidgetAjaxController::progress. You need to return a JSON-encoded associative array with message and percentage keys. For example:
$progress['message'] = t('Uploading... (@current of @total)', ['@current' => format_size($status['bytes_uploaded']), '@total' => format_size($status['bytes_total'])]);
$progress['percentage'] = ...
It should be easily done like this:
$form['submit']['#ajax'] = [
'callback' => 'MYMODULE_submit_throbber_callback',
'progress' => [
'type' => 'throbber',
'message' => NULL,
And then return $form in the callback;
I actually found the answer myself. Using the Better Exposed Filters module did the trick.
From the module's description:
Provide instant feedback by updating the View using AJAX whenever an exposed filter is changed.
Actually, you will pass through your validateForm() method, whether you are using Ajax or not.
In the validateForm(), you have to set the appropriate errors on your fields which do not validate.
Then, as Charles Bamford stated, you need to handle the error management in your submit callback.
So basically, you would end up with some kind of the following ...