Here is snippet code to display the error message in popup: (Core: Login form)
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\ReplaceCommand;
use Drupal\Core\Ajax\CloseModalDialogCommand;
use Drupal\Core\Ajax\RedirectCommand;
function login_popup_form_alter(array &$form, FormStateInterface $form_state, $form_id) {
if ($form_id == 'user_login_form') {
// Check if the current request is for an Ajax modal/dialog.
if (login_popup_is_dialog() == TRUE) {
// Add a wrapper around the form so that we can replace it.
$form['#prefix'] = '<div id="modal_user_login_form">';
$form['#suffix'] = '</div>';
// The status messages that will contain any form errors.
$form['status_messages'] = [
'#type' => 'status_messages',
'#weight' => -10,
];
// Add form validation to the submit btn & make it Ajax.
$form['actions']['submit']['#validate'] = $form['#validate'];
$form['actions']['submit']['#attributes']['class'][] = 'use-ajax';
$form['actions']['submit']['#ajax'] = [
'callback' => 'login_popup_submit_modal_form_ajax',
'event' => 'click',
];
}
}
}
/**
* AJAX callback that displays the form errors or redirects to page.
*/
function login_popup_submit_modal_form_ajax(array $form, FormStateInterface $form_state) {
$response = new AjaxResponse();
// If there are any form errors, re-display the form.
if ($form_state->hasAnyErrors()) {
$response->addCommand(new ReplaceCommand('#modal_user_login_form', $form));
}
else {
// On successfully form submission close dialog & redirect to the user page.
$response->addCommand(new CloseModalDialogCommand());
$uid = \Drupal::currentUser()->id();
$redircet_path = Url::fromRoute('entity.user.canonical', ['user' => $uid])->toString();
$response->addCommand(new RedirectCommand($redircet_path));
}
return $response;
}
* Is the current request for an Ajax modal/dialog.
*
* @return bool
* TRUE if the current request is for an Ajax modal/dialog.
*/
function login_popup_is_dialog() {
$wrapper_format = \Drupal::request()->query
->get(MainContentViewSubscriber::WRAPPER_FORMAT);
return (in_array($wrapper_format, [
'drupal_ajax',
'drupal_modal',
'drupal_dialog',
'drupal_dialog.off_canvas',
])) ? TRUE : FALSE;
}
Note:
#1 This below code is required so that the core(login) form validation fire in popup,otherwise inbuilt validation of core(login) form will not fire/display in popup.
$form['actions']['submit']['#validate'] = $form['#validate'];
Explanation:
Any core/contrib(inbuilt) form that we want to just display in popup, but face problem that validation error not display in popup:
To reuse form validation instead of writing duplicate code, solution behind this problem:
Get the validation definition of core/contrib(login) form in hook_form_alter > set the validation definition in the "#validate" variable in submit handler of popup form.
#2 login_popup is module name, can update "login_popup" as per your module name.
#3 login_popup_is_dialog : Custom function used to determine whether form is open in modal or not, if form is not opened is modal
then is no point to add this code.