Как временно убрать признак обязательного (required) поля формы?

Аватар пользователя Sun-fire Sun-fire 9 июня 2011 в 13:15

Суть задачи.

Перехватываю по hook_fork_alter() форму редактирования ноды. Для определенных ролей добавляю на нее дополнительную кнопку, при нажатии на которую необходимо сохранять содержание формы, не обращая внимания на то, что некоторые обязательные поля могут быть пустыми. Такая себе опция промежуточного "быстрого" сохранения.

Добавил свой хук валидации к форме, в котором перехватываю событи валидации формы при нажатии кнопки. Вызов функции валидации происходит, в нем для обязательного поля устанавливаю статус #required = FALSE, но валидация все равно гавкает, что поле обязательное, и форму соответственно не сабмитит.

В чем может быть проблема?

Комментарии

Аватар пользователя Sun-fire Sun-fire 9 июня 2011 в 13:35

Выдержка из кода:


<?php

function mymodule_form_alter(&$form, &$form_state$form_id) {

...
    
    

$form['prsave'] = array(
        
'#weight' => '-3',
        
'#id' => 'timeout',
        
'#type' => 'button',
        
'#value' => 'Проміжне зберігання',
        ); 
        
        
$form['#validate'][] = 'mymodule_form_validate';
        
$form['actions']['submit']['#submit'][] = 'mymodule_form_submit';
}

function 

mymodule_form_validate($form, &$form_state) {
     switch (
$form_state['clicked_button']['#id']) {
     case 
$form['prsave']['#id']:
       
$form ['field_ram_capacity_relation']['uk']['#required'] = FALSE;
     break;
   }   
}

?>
Аватар пользователя Sun-fire Sun-fire 9 июня 2011 в 13:47

Так вот и трабл то в том, что если убрать обязательность в hook_form_alter(), то она (обязательность) уберется вообще. А нужно, чтобы она убиралась только для "быстрого" сохранения, а для полноценного сабмита по стандартной кнопке "Сохранить" оставалась.

Аватар пользователя Sun-fire Sun-fire 9 июня 2011 в 15:06

С проверкой значений нажатой кнопки в $form_state через hook_form_alter() тоже проблема. Согласно схеме обработки форм в Drupal 7, вызов hook_form_alter() происходит, если форма не прокэширована в текущей сессии. Если форма к кэше есть, то она отдается, миную вызов hook_form_alter().

Для проверки поставил в hook_form_alter() проверку на нажатие какой-либо из кнопок, даже не целевой:

if (isset($form_state['clicked_button']['#id'])) {
$form ['field_ram_capacity_relation']['uk']['#required'] = FALSE;
}

соответственно, ноль реакции, поскольку форма на вилидацию пошла из кэша.

Аватар пользователя Sun-fire Sun-fire 9 июня 2011 в 16:44

dsm($form_state) прописан в hook_form_alter()

При первой загрузке формы dsm($form_state) начально значение $form_state, в котором форма не просабмичена:

submitted (Boolean) FALSE
executed (Boolean) FALSE

$form_state['clicked_button'] не проинициализировано.

При нажатии на кнопку сабмита формы dsm($form_state) вообще не отображается.

Пока нашел следующий выход из ситуации:

по hook_form_alter() смотрю поля, и для тех, которые обязательны к заполнению изменяю #element_validate на кастомный обработчик валидации. В этом обработике в зависимости от нажатой кнопки буду:
-разблокировать поле, с дальнейшей выдачей на сохранение;
-отдавать на стандартную валидацию вызовом соответствующей функции с подальшей выдачей на сохранение или возвратом в форму если поле не заполнено. Предварительно работает, но пока тестировал только на одном поле, имя которого захардкодил в модуле. Сейчас пишу универсальный обработчик, который будет автоматически просматривать поля и подменять их валидаторы.

Аватар пользователя Sun-fire Sun-fire 9 июня 2011 в 18:35

Два аналогичных поля, разница только в виджетах. Для обоих переопределена функция валидации. Одно через валидацию проходит, второе нет. Танцы с бубном вокруг валидатора...

Аватар пользователя ydv ydv 15 декабря 2011 в 20:09

Тут можно было пойти путем от обратного. Все поля по умолчанию ['#required'] = FALSE;
в my_custom_form_validate(&$form, &$form_state) {} делаем следующее

<?php
function my_custom_form_validate(&$form, &$form_state) {
  
// Validate the postal code is entered when Ireland is not selected.
  
if ($form_state['values']['country'] != 'ireland' && empty(trim($form_state['values']['postal']))) {
    
form_set_error('postal't('The Postal code is required.'));
  }
}
?>

нашел здесь http://drupal.org/node/739742