I know that, when I want to run off the #require property of a field in hook_form_alter(), I just need to set #require property of a specific field to FALSE.

How can I remove the #required property of all the required fields? I want to make the fields not required when the user has a specific role.

Do you have any idea?


If you're ok with the risks that this might well pose to the integrity of your content you could probably use a simple recursive script like the following in a form alter function:

function MYMODULE_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'myform_name') {
    $form['#after_build'][] = '_MYMODULE_remove_required';

function _MYMODULE_remove_required(&$element) {
  $element['#required'] = FALSE;

  foreach (element_children($element) as $key) {
  • 1
    good solution Clive, what is your idea about below answer? – Yusef Sep 17 '12 at 12:13
  • Putting it in #after_build is probably a good idea, but your recursive function isn't recursing at the moment! – Clive Sep 17 '12 at 12:15
  • Notice that the #after_build function is required to return the element it gets as argument, which is not passed as reference. See system_check_directory(), used in system.admin.inc. – kiamlaluno Sep 17 '12 at 18:36
  • +1 just for showing use of element_children(), really useful, and helped me disable all form elements easily – chim Mar 4 '13 at 16:31
  • In Drupal 8, you'll use Element::children instead of element_children. – Gogowitsch Jul 8 '17 at 10:15
   function hook_form_alter(&$form, &$form_state, $form_id) {
     if ($form_id == 'myform_name') {
       if (in_array('administrator', $user->roles) {
         $form['#after_build'][] ='mymodule_recursive_unrequired';

   function mymodule_reqursive_unrequired($element) {
     foreach (element_children($element) as $name) {
       $element[$name]['#required'] = FALSE;

     return $element;

I didn't test it yet; it is just an idea.

  • 1
    The #after_build functions are required to return the element it gets as argument, which is not passed as reference. See system_check_directory(), which is the #after_build function used in system.admin.inc. – kiamlaluno Sep 17 '12 at 21:56
  • @kiamlaluno , I got this idea from a module disable all form element and worked for me.hoever thanks for antention. – Yusef Sep 18 '12 at 4:18
  • You just need to remove the & in function mymodule_reqursive_unrequired(&$element), and then is all fine. I would rather accept your answer, as at least it correctly returns $element. – kiamlaluno Sep 18 '12 at 4:41

I used this answer and thought I'd share some improvements:

As above, add the following function as an #after_build callback for the appropriate users.

 * Removes "required" from all form elements.
 * Use at your own risk.
 * Use:  in a _form_alter function, $form['#after_build'][] = 'MYMODULE_remove_required';
 * @param array $element
 * @param array $form_state
 * @param int $depth
 * @return mixed
function MYMODULE_remove_required($element, &$form_state, $depth=0) {
  if ( $depth > 6 ) return $element; // put a limit on recursion
  if ( !empty($element['#required']) ) $element['#required'] = FALSE;
  // only iterate over children for likely elements
  if ( empty($element['#type']) || !in_array($element['#type'], array('radios','checkboxes')) ) {
    foreach ( element_children($element) as $name ) {
      $element[$name] = MYMODULE_remove_required($element[$name], $form_state, $depth+1);
  return $element;
  • This is the only one I could get to work – ja_him Jan 29 '15 at 15:30

You can also try Required by role module.


UPDATE: The solution I posted seems to be a bad idea. When you reset the $form_state['values'] array, what is actually happening is that you are removing the form token id. You could get the same effect by adding:

$form_state['values']['form_token'] = false;

This seems like a bad idea especially if you have multiple content editors. This also creates a Drupal error message:

The form has become outdated. Copy any unsaved work in the form below and then reload this page.

ISSUE: I have an issue with field_collections (embedded). I am unable to add/remove items.

This worked perfectly: https://drupal.stackexchange.com/a/56350/72908

Basically you just need to reset the $form_state['values'] array in your #after_build function.

     * Implements hook_form_alter().
    function modulename_form_alter(&$form, &$form_state, $form_id) {
      if ($form['type']['#value'] == 'YOUR FORM TYPE') {
        $form['#after_build'][] = 'custom_function_after_build';

    function custom_function_after_build($form, &$form_state) {
      $form_state['values'] = array();
      return $form;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.