我使用“use-ajax”类在模式中呈现登录表单。我想在同一模式上处理验证错误而不关闭它。成功登录后,它会正确重定向,但是当发生错误时,它会关闭模式并重定向到登录页面,即用户/登录并在该页面上显示错误。我尝试使用 ajax 回调通过更改正在工作的表单来显示模式本身的错误。但是,它给了我 drupal ajax 错误。这是我的代码:
$form['#prefix'] = '<div id="modal-form">';
$form['#suffix'] = '</div>';
$form['status_messages'] = [
'#type' => 'status_messages',
'#weight' => -10,
];
$form['actions']['submit']['#ajax'] = array(
'callback' => 'setMessage',
'wrapper' => 'modal-form',
);
====================================================== ========================
function setMessage(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
$response = new AjaxResponse();
if ($form_state->hasAnyErrors()) {
$response->addCommand(new ReplaceCommand('#modal-form', $form));
}
else {
$command = new CloseModalDialogCommand('#modal-form', FALSE);
$response->addCommand($command);
}
return $response;
}
上面的代码也给了我会话 ID,但由于 drupal ajax 错误,它不会通过关闭模式成功重定向。
如果我使用非ajax ie。如果我删除 ajax 回调函数,它会成功,但错误不会显示在模式上。
首先,检查您是否在模块文件中使用 hook_login 添加了与重定向相关的更改。您可以删除与重定向相关的更改并在回调函数中处理重定向。
function setMessage(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
$response = new AjaxResponse();
$current= \Drupal::currentUser();
if ($form_state->hasAnyErrors()) {
$response->addCommand(new ReplaceCommand('#modal-form', $form));
}
else if (!$current->id()) {
$response->addCommand(new ReplaceCommand('#modal-form', $form));
}
else {
$command = new RedirectCommand(' ');
return $response->addCommand($command);
}
return $response;
}
成功后,它将关闭模式并正确重定向。如果您发现任何错误或者您尚未登录,它将保留在模式表单中。
这里是在弹出窗口中显示错误消息的代码片段:(核心:登录表单)
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;
}
注:
#1 下面的代码是必需的,以便核心(登录)表单验证在弹出窗口中触发,否则核心(登录)表单的内置验证将不会在弹出窗口中触发/显示。
$form['actions']['submit']['#validate'] = $form['#validate'];
说明: 我们只想在弹出窗口中显示的任何核心/贡献(内置)表单,但面临验证错误未在弹出窗口中显示的问题:
要重用表单验证而不是编写重复的代码,这个问题背后的解决方案:
在 hook_form_alter 中获取 core/contrib(login) 表单的验证定义 > 在弹出表单的提交处理程序中的“#validate”变量中设置验证定义。
#2 login_popup 是模块名称,可以根据您的模块名称更新“login_popup”。
#3 login_popup_is_dialog : 自定义函数,用于判断表单是否以模态方式打开,如果表单未打开则为模态 那么就没有必要添加这段代码了。