Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
By tarnus on
I need to add an extra function to a node form after it has submitted. In drupal 7 all I had to do was add a submit handler. Everywhere I look the same thing was said about drupal 8, however I can't get the submit handler to trigger.
Here is the code I tried:
// Implements HOOK_form_BASE_FORM_ID_alter
function mymodule_form_node_form_alter(&$form, FormStateInterface $form_state) {
$form['actions']['submit']['#submit'][] = 'mymodule_node_form_submit';
}
function mymodule_node_form_submit($form, FormStateInterface $form_state) {
// mymodule_do_something($node);
\Drupal::logger(' mymodule')->notice('mymodule submit ') ;
}
I'm stumped on this. The alter is working, 'mymodule_node_form_submit' is being added to the submit array, its just not executing the function.
Anyone have any ideas?
Thanks.
Comments
Solved!
Figures I would post this and then solve the problem on my own.
After searching through modules for drupal 8, I finally found one that had a submit handler. Here is updated code for those of you that have the same issues I had.
Thank you @tarnus, I found
Thank you @tarnus, I found myself in the exact same situation and this was very helpful.
Thanks, saved my day.
Thanks, saved my day.
Thanks, worked for me too!
Thanks, worked for me too!
How can I update the field value in submit
If I want to update any values in the form submit , how can I handle . Inside second submit I have tried with $form_state->setValue(['field_name',0,'value'], 10); , but this is not updating the field .
use $form_state->setValueForElement()
As far as I have understood the way to change the values in the FormState is using FormState::setValueForElement() in the validate function of your form, so the values will arrive to the main submit function already updated.
Two more solutions for updating field value in submit callback
On top of @marcoscano's reply, I would like to add two other methods I've been using in projects, and more specifically answering the question:
1 - Running submit callback before Core's and all others: array_unshift vs array_push
Basically, the solution suggested by @tarnus, above, adds a submit callback after all the existing ones:
which pretty much corresponds to an array_push, which pushes the passed callback onto the end of the stack (running the callback after all others).
Using array_unshift instead prepends passed callback to the front of the array. In other words, the added callback runs before all others, including Core's, which takes care of saving the entity.
The idea is similar to what was suggested above by @marcoscano: Altering form's or entity's values before they are saved through Core's regular process/flow.
2 - Saving the form/entity in the submit callback
Sometimes, there's no choice and the custom callback has to run after all others, in which case array_push (
$array[] = $var
) has to be used.In this case, the form/entity has already been saved (through Core's submit callbacks), thus leaving the saving process at our charge:
Here is an example of how things could potentially be handled:
Now, watchout how the values have to be set for entity's values, since the format is most likely different from the one used for the fields in the form.
I hope this comment will help answering some of your questions and further complete the initial post.
All this is still kind of new for me as well and I would be very happy to hear your feedbacks, comments or ideas on what could be a more ideal approach for this kind of problems.
Thanks in advance to everyone for your testing, reviews, reporting and feedback.
Many thanks to @tarnus for getting the ball rolling on this ;-)
One Question regarding saving entity in submit handler
Does the core submit handler doesn't create another node since it will also save the entity??
It worked!
I was facing same issue, this helped me.
Thanks :)
FormStateInterface no longer exist.
Hi,
Currently using Drupal 8.1, in this version
FormStateInterface
no longer exist, instead of this we need to use\Drupal\Core\Form\FormStateInterface
.So am changing Form submit handler as,
I am able to get submitted
I am able to get submitted values inside submit handler , only issue was I want to update any field value after a form submit .
But the entity save inside submit handler is working
$entity = $form_state->getFormObject()->getEntity()) {
$entity->set('MY_FIELD_NAME', $value);
$entity->save();
FormStateInterface was imported.
I assume in OP's code the FormStateInterface's class was imported with a "use" statement.
It is not like the FormStateInterface doesn't exist anymore, but you can leave out the full namespace if you import it beforehand.
@arunkumark
Yes, the class FormStateInterface still exists for any versions of Drupal 8 (thing is you ARE using it in your code), but since it lives in the \Drupal\Core\Form\ namespace, if you want to use it simply by its name, you need to declare the use of this particular class in its particular namespace at the beginning of your script.
Hope it'll save you some time next time ;-)
Drupal 8.2 example that worked for me
In your example you have $form['actions']['submit']['#submit'][] = 'mymodule_form_submit_handler'; then have function example_form_submit_handler down below. This may be confusing to other and won't work, but I see what you meant to write. It should read " $form['actions']['submit']['#submit'][] = 'example_form_submit_handler'; ".
So if someone has a module named "FOO" and their form id is "apples_and_oranges_form" the the HOOK_form_FORM_ID_alter should read:
function foo_form_apples_and_oranges_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state)
{
.....your code
$form['actions']['submit']['#submit'][] = 'name_this_something_its_a_custom_function';
}
AND
function name_this_something_its_a_custom_function($form, \Drupal\Core\Form\FormStateInterface $form_state) {
//note: do yourself a favor and insert the devel module so you can use the kint method for pretty arrays.
kint(Rform_state);
}
Most importantly...i'm using Drupal 8.2.x and I had to use $form['#submit'][] = 'my_custom_function' vs $form['actions']['submit']['#submit'][] like in this example.
This really helped. Many Thanks.
When a node is submitted , i had to create multiple nodes depending on the values set in form. The code above(one by @DYdave) was straight cut answer for what i was searching.
Hope this will help (Submit handler d8)
1) add following line at the top of your module
use Drupal\Core\Form\FormStateInterface;
2) add the following submit handler & custom function
a) Submit handler:-
b) Custom function:-
The above code is adding handlers at button level.
There are chances you might get entity validation skipped error if you are using the button level handlers above.
Then maybe you can call validate method on entity in your handler or write form level handler.
All validation handlers are
All validation handlers are executed before any submission handlers are executed, so adding button level handlers will not cause any validation issues.
What if i add custom validate functions like this??
What's the question?
**Edit** - the comment below is incorrect for Drupal 8.
In Drupal 6 and Drupal 7, #validate attached to a submit button is never called - only #element_validate attached to elements, and/or #validate attached to the root of the form are called. I haven't checked if it's changed in D8, but it probably hasn't, so I suspect that validate handler will never be called, and it has nothing to do with having added a submit handler to the button.
Check the below link.
The validation handlers added the above way are working in my case in D8.
Check this link out: https://www.drupal.org/node/2453175
You're right, I just did a
You're right, I just did a test, and #validate does work on a submit button.
Now that that's straightened out, what's your question?
When i add a validate handler
When i add a validate handler to button, i'm getting a entity validation skipped error. If i shift that handler to form, the error is gone. I donno if this is the only reason, but just happened to get that.
That's the same as submit
That's the same as submit handlers attached to buttons. If/when a submit (and apparently validation) handler is attached to the button, the submit (and apparently validation) handlers attached to the form are not called. This is why you are seeing the issue that you have.
You have two options:
1) Also attach the default validation handler(s) to the button, or:
2) Add your validation handler to the form (which you already discovered)
Thanks Jaypan.
Thanks Jaypan.
I try to upgrade module to d8
I try to upgrade module to d8,
i used hook_form_alter() to hide mail field from register form, so user don't need email when they create new account. i want function automatic give new user fake email according the register name, otherwise there are error about "email field is required".
i added custom validation by
how to make _mymodule_validation2 function called as first validation function? this is the place i modify mail value.
my d7 module is working but in d8 is not.
Still facing the issue in getting submit handler
The code I tried:
But still it gives me error "Warning: call_user_func_array() expects parameter 1 to be a valid callback, function 'my_theme_form_system_theme_settings_submit' not found or invalid "
Using Drupal 8.2.5, Am I missing something here?
It's saying that my_theme
It's saying that
my_theme_form_system_theme_settings_submit()
cannot be found. In what file is this code located? It needs to be in the .module file, or the file in which it is located needs to be manually loaded ahead of time.It's in theme-settings.php
It's in theme-settings.php
You'll need to move it to
You'll need to move it to your .module file, or else call form_load_include() in your hook_form_alter() implementation, and include theme-settings.php there.
hook_form_BASE_FORM_ID_alter in Drupal 8.4.3
if using hook_form_BASE_FORM_ID_alter in Drupal 8.4.3, I found the ways of adding the custom submit handler listed above didn't work. This worked for adding the submit handler function name:
$form['#submit'][] = 'mymodule_submit_handler';