Last week, I was trying to add a custom validation method for node form of a particular content type in Drupal. My initial approach was as naive as specifying my custom validation method in hook_form_alter, something like the following:
{syntaxhighlighter brush: php;fontsize: 100; first-line: 1; }function mymodule_form_alter(&$form, &$form_state, $form_id) {
switch($form_id) {
case ‘artist_node_form’:
$form[‘#validate’][] = ‘_mymodule_custom validation’;
break;
}
}{/syntaxhighlighter}
However my custom validation method was not always called when the node form was submitted. Confused, on a little testing and stepping through the Drupal code, I found that the custom validation method was only called when all core Drupal validation methods on the node form succeeded. If any native validation on the node form (where native means the validations performed by Drupal on the submitted form content based on your assocaited content type’s settings) failed, then the custom validation method was not called.
And this was not what I wanted. This meant that the user did not see all data entry errors on the form together. Only when the first set (i.e. Drupal’s validations) on the form passed was the next set of validation methods (i.e. the custom validation methods on the node form) were invoked. So, after getting errors first time, correcting those and re-submitting, the user might again get validation failures triggered by custom validation, which was not very user-friendly.
Clearly I needed a way to somehow tell Drupal to always invoke the custom validation method on each form submission, so that all validation errors could be shown to the user together.
After some playing around, I decided to hook my custom validation method in the #after_build method instead of doing it in hook_form_alter. So, the updated code looked something like the following:
{syntaxhighlighter brush: php;fontsize: 100; first-line: 1; }function mymodule_form_alter(&$form, &$form_state, $form_id) {
switch($form_id) {
case ‘artist_node_form’:
$form[‘#after_build’][] = ‘mymodule_custom_after_build’;
break;
}
}
function mymodule_custom_after_build($form, &$form_state) {
$form[‘#validate’][] = ‘mymodule_custom_validation’;
return($form);
}
function mymodule_custom_validation($form, &$form_state) {
//My custom validations went here.
}{/syntaxhighlighter}
Here I specify #after_build method for the node form in hook_form_alter. Then in the #after_build method, I specify the #validate method for the custom validation I needed.
And it now worked exactly as I needed. My custom validation method was always called which meant all input errors were shown to the user together on each form submission for the node form.
An important point to take care above is that you need to return the $form object from the #after_build method, or it won’t work.
It lacked sense to me that Drupal does not invoke the additional validation methods when specified directly in hook_form_alter but invokes them when spcified in the after_build method for the form. I searched a bit and found this issue being reported on the official Drupal issue queue on drupal.org, but which was closed with a comment that it works as designed. For me, this is not the correct design, but then, every developer has his own way of looking at things…
Atleast there’s was way to have it done so that functionally it behaves as you want it to.
Nice tip, thanks! 🙂
Hey dear Thats nice idea to add one extra validation array elimant in node_validation
This is usefull for me
thanks …
Nice Tip. You are my hero!!!
Thanks your post helped me. 🙂
Great article! One small improvement would be to include some validation code in the
mymodule_custom_validation() function, I think this would be useful.
Thanks
Thank you!! Saved me lots of time!!
Thanks a lot. Greetings from Florianópolis, Santa Catarina, Brazil.
Really nice article. Thx!
Thank you for your help. I need some add. When I do this not return to form but shows the comment.
How do I post when validation fails?
My code is :
function shiftvalidation_form_alter(&$form, &$form_state, $form_id) {
print_r($form_id) ;
if ($form_id ==’work_schedule_node_form’) {
$form[‘#after_build’][] = ‘shiftvalidation_after_build’;
echo ‘<br />’ . $form[‘taxonomy’][3][‘#title’] . ‘<br />’ ;
}
}
function shiftvalidation_after_build($form, &$form_state) {
$form[‘#validate’][] = ‘shiftvalidation_shift_validate’;
return($form);
}
function shiftvalidation_shift_validate($form, &$form_state) {
echo ‘This is a test’ ;
}
Can you help me ?
Thanks.
Manuel.
Thank you so much! Just wish I had found you a couple weeks ago…
This example was very helpful.
Thanks, works brilliantly!
Do the $form_id is available in the custom after build function? When I tried to call form_id in this function, I got the warning “missing parameter 3” or can we pass any custom varaible to after build function?
Yes, I got the id in $form[‘#form_id’].. Thanks a lot…
I can use #after_build and #validation in form_alter of edit node, I upload images in field_collection but not start validation when save node. Any ideas? Thanks.
thanks, this article save me a lot of time and headache.
thanks again.
Amazing blog here, some interesting ideas and thoughts. Appreciate your efforts and hope you will keep on producing such a quality content. Wish you good luck, thanks!
Hello rahul,
Can you help to override the content type submit button function to my own function. I want to submit that data into different custom table.
Thanks !!