I'm creating a custom field element type that contains other interactive elements. I've been following the Drupal core File module to try to simulate some of the functionality of it. One thing I've been having trouble with is submission and validation errors.
When you upload a file using the File module, only that part of the form seems to be submitted. In my module, the whole form gets submitted instead. I'd really like to have it act like the File module by only submitting my one element and its contained elements.
The other thing is validation errors. In the file module when you run into an error with an uploaded file, the validation error appears within the area where the file field appears instead of the top of the page. I also have the trouble of my validation for that field being checked when I submit the whole form, but I don't want this validation to happen for submitting the whole form. I only want validation when I hit the button within my custom element like file validation works.
Here's what I have so far. I apologize that this is regarding the same code as a previous question, but that was about the overall framework to use and this is specifically asking about issues with submission and validation for this custom element.
/**
* Implements hook_element_info().
*/
function my_module_element_info() {
$types['user_management'] = array(
'#input' => TRUE,
'#process' => array('my_module_user_management_process'),
'#size' => 45,
);
return $types;
}
/**
* Implements hook_form_FORM_ID_alter().
*/
function my_module_form_my_module_node_form_alter(&$form, &$form_state) {
$form['administrators_management'] = array(
'#title' => t('Account Administrators Management'),
'#type' => 'fieldset',
'#description' => t('Administration for users who have administrative access to this account.'),
'#weight' => 33,
);
// unset($form['my_module_administrators']);
$form['administrators_management']['user_management'] = array(
'#type' => 'user_management',
);
}
/**
* Process function to expand the user_management element type.
*/
function my_module_user_management_process($element, &$form_state, $complete_form) {
global $user;
$element['#tree'] = TRUE;
// Normal FAPI field definitions, except that #value is defined.
$element['user_email'] = array(
'#type' => 'textfield',
'#title' => t('Enter email address to add new administrator user'),
'#size' => 45,
'#maxlength' => 100,
'#prefix' => '<span id="user_email">',
'#suffix' => '</span>',
'#element_validate' => array('my_module_user_management_validate'),
);
$element['add_button'] = array(
'#type' => 'submit',
'#value' => t('Add User'),
'#submit' => array('my_module_user_management_submit'),
'#validate' => array(),
'#limit_validation_errors' => array($element['#parents']),
);
$element['administrators'] = array(
'#type' => 'select',
'#title' => t('Account Administrators'),
'#default_value()' => array(),
'#options' => field_view_field('node', $complete_form['#node'], 'my_module_administrators'),
'#multiple' => TRUE,
);
return $element;
}
/**
* An #element_validate callback for the user_management element.
*/
function my_module_user_management_validate(&$element, &$form_state) {
if (!array_key_exists('user_management', $input = $form_state['input'])
|| !array_key_exists('user_email', $user_management = $input['user_management'])
|| !($email_address = $user_management['user_email'])) {
form_set_error('user_management][user_email',
t("An email address must be entered before pressing 'Add User'."));
} else { // if $form_state['input']['user_management']['user_email'] has a value
if ($email_address && !filter_var($email_address, FILTER_VALIDATE_EMAIL)) {
form_set_error('user_management][user_email',
t("User email must be a valid email address."));
}
}
}
/**
* Form submission handler for add / remove buttons of user_management elements.
*/
function my_module_user_management_submit($form, &$form_state) {
$email_address = $form_state['input']['user_management']['user_email'];
$administrators_options[strval(count($administrators_options))] = $email_address;
$form_state['rebuild'] = TRUE;
}
/**
* Implements hook_node_submit().
*/
function my_module_node_submit($nodes, $form, &$form_state) {
$administrators_options = $form['administrators_management']['user_management']['administrators']['#options'];
foreach ($administrators_options as $email_address) {
$new_user = user_load_by_mail($email_address);
if (!$new_user) {
$new_user = new stdClass();
list($name) = explode('@', $email_address);
for ($temp = $name, $count = 1; user_load_by_name($temp); $temp = $name . ++$count);
$new_user->name = $temp;
$new_user->mail = $email_address;
$new_user->init = $email_address;
$new_user->status = TRUE;
$new_user->roles = array(
DRUPAL_AUTHENTICATED_RID => TRUE,
db_query("SELECT rid FROM {role} WHERE name = 'customer'")->fetchField() => TRUE,
db_query("SELECT rid FROM {role} WHERE name = 'customer admin'")->fetchField() => TRUE,
);
$new_user = user_save($new_user);
}
}
}
#ajax
on any of your elements so that would probably account for the behaviour you're getting, which would be that of a standard form