To reproduce this problem:
- Create a new form
- Add an element to the form with '#element_validate' => some_function
- Set the #limit_validation_errors to array() (meaning you want to limit ALL validation)
- Now submit the form
.
The validation function runs; the expected behavior is that these functions would not be run, no? It should be noted that errors set by form_error are not displayed (which is good), but this is still a problem when the validation function in question sets (or unsets) some values in $form_state. In addition, these see like wasteful function calls to me... am I missing something?
| Comment | File | Size | Author |
|---|---|---|---|
| #29 | 1488294-29.zip | 1.34 KB | valthebald |
| #25 | test.zip | 2.44 KB | bleen |
| #22 | example-1488294.module.txt | 1.03 KB | valthebald |
Comments
Comment #1
jaypanI'm seeing this in D7 as well.
Comment #2
jaypanComment #3
bleen commented@Jaypan - Bugs like this always need to be fixed in the latest dev version (in this case 8.x) before it can be back-ported to previous versions. Also, while this bug is tremendously annoying, it does not really meet the definition of major outlined here: http://drupal.org/node/45111
Comment #4
jaypanFair enough. Thank you for setting it correctly.
Comment #5
drifter commented[never mind, didn't read the issue carefully, mine was about a different edge case]
Comment #6
valthebaldIf you have a form with required element, and dependent select boxes (i.e. Country/State), population via #ajax won't work (because form validation breaks on required element).
There are hacks to overcome that, but of course current behavior is annoying.
IMO this can qualify this issue as 'major'
Comment #7
tim.plunkettThis does not "have significant repercussions", it "affect[s] one piece of functionality are normal priority".
See the handbook page linked to in #3.
Comment #8
jaypanI never actually read the page that was linked to until now, but looking at it, for an error marked 'major', the handbook states:
For me it has quite significant repercussions. I have a form that is essentially the major focal point for the system I'm currently building. This issue was causing errors to popup every time the form was used (I had to hack a way around it). The fact that it is a Drupal error and not a PHP error is a minor point in my mind, it still affects the functionality of the system as a whole for my users, even though it doesn't render the whole system unusable.
As such, I'm actually of the opinion that my original status of 'major' was in fact correct. I'm just a single person though, so I will not change the status of this Issue. But I feel that marking as normal is in fact incorrect and is doing a disservice to anyone who may be using a 3rd party module that has #element_validate set, and can only fix this issue by hacking the module code or core.
Comment #9
valthebaldI want to keep this issue.
Also, I think it's worth adding a test to prevent wrong behavior in the future
Comment #10
bleen commentedby "keep this issue" do you mean you are planning on working on it and submitting a patch? If so, awesome!! if not, please assign it back to Anonymous :)
Comment #11
valthebaldWorking on the patch already...
Comment #12
valthebaldTL;DR - issue does not exist, add '#button_type' to the calling select box
Long version:
I've started to build test case for D8 to simulate problematic behavior, and quickly found, that it's not reproducible.
I've digged into dark magic of form.inc, and found the following (starting from line 1380 in D8, same exists in D7 branch):
Another issue is related to form_builder() function.
If the logic that populates dependent select box values, looks into $form_state['values'], but not $form_state['input'] (it should do so, because $form_state['values'] are safer), it may found empty value. Reason is located in form_builder(), starting from line 1175:
So, there are good chances triggering element's value just doesn't find it's way to $form_state['values']
After some more investigation, I found
a) original issue #684846: AJAX triggered by non-submit element fails if any elements are validated and
b) chx's blog post at http://www.drupal4hu.com/node/286
Example code that checked and works both with 8.x and 7.x:
form definition:
And AJAX callback:
Comment #13
jaypanThis is a very real problem that I just faced yesterday. If 'works as designed' means that it's designed not to work, then you are correct. But right validation is being called on elements with #element_validate, even when #limit_validation_errors is set to an empty array(). Maybe it's been fixed for D8, but in D7, the problem exists.
Comment #14
jaypanI should add, in your example you didn't use #limit_validation_errors.
Comment #15
bleen commentedPlease follow the steps to reproduce in the original post:
"some_function" should not be called in this case, but it is (which is a bug)
Following these steps *does* produce the error as reported.
Comment #16
valthebaldDo you mean that the same element has #element_validate and empty #limit_validation_errors? What's the use case for that?
Comment #17
bleen commented#16: no ...
Comment #18
valthebaldFrom Form API documentation:
Could you add #submit and retry?
Comment #19
bleen commentedSame...
... I'm not sure why you are persisting with such vigor to show that this is not an error. It is, and it has been confirmed by several people. If you can concretely show that this is "as designed" please provide some example code. I'd love to look at something like that so we can have a real discussion about this issue being closed or so that we can get past the doubts and move towards coming up with a fix...
Comment #20
valthebald#19:
Since you have different submit elements, which one is clicked?
Comment #21
bleen commentedthe one with the #limit_validation_errors
Comment #22
valthebaldI've attached proof of why current behavior does not contain bug mentioned in this issue (should be saved as example.module, URL to test is example_menu_item
Please note that in button declaration
both #submit and #limit_validation_errors are mandatory.
You can comment out any of these line and see that form will start returning validation errors
Comment #23
jaypanAnd how is that not a bug?
Comment #24
valthebald#23: The code attached works exactly as it explained in API documentation.
Where's the bug?
Comment #25
bleen commentedOk ... I can confirm that the sample module in #22 works as designed. It appears that this issue is a bit more complex and it is related to using Ajax to add a new form element that has a validation function. Attached is a sample module that demonstrates this error. To reproduce, install the attached module and go to mysite.com/test-menu-item , fill in the text field and click the "Add another text field" button.
Error is seen...
Comment #26
bleen commented... the module in #25 is for D7
Comment #27
bleen commented...also, thanks valthebald for putting some code on paper so we can finally move this forward
Comment #28
chanderbhushan commented<?php
function modulename_menu() {
$items['example_menu_item'] = array(
'page callback' => 'drupal_get_form',
'page arguments' => array('my_form'),
'access arguments' => array('access content'),
);
return $items;
}
function my_form($form, &$form_state) {
$form['test'] = array(
'#type' => 'textfield',
'#title' => 'Text field',
'#element_validate' => array('test_element_validate'),
);
$form['button'] = array(
'#type' => 'submit',
'#value' => 'Submit',
'#submit' => array('test_button_submit'),
'#limit_validation_errors' => array(),
);
$form['#submit'] = array('test_submit_handler');
return $form;
}
function test_submit_handler($form, &$form_state) {
drupal_set_message('Submit callback called');
}
function test_button_submit($form, &$form_state) {
drupal_set_message('Button callback called');
}
function test_element_validate($form, &$form_state) {
form_set_error('text_el', 'This element never validates');
}
Comment #29
valthebaldI guess we are slowly entering area of Form API dark magic...
First, module attached to #25 not exactly serves it's purpose (by the way, same code works for D8 as well)
It doesn't add new text fields, even when error messages are off.
Attached please find slightly changed module that does the trick
You can uncomment line 68:
to see that element validate callbacks are called.
Additional textboxes appear with or without drupal_set_message() call.
Commenting line 42:
leads to additional textboxes not appearing, and form error.
Conclusion: #element_validate handlers are called always. #limit_validation_errors let us ignore validation results and proceed to submit callbacks.
Is that a bug? I would say no, because I can imagine several reasons why such behavior could be developed on purpose.
Probably we can ask one of the Form API maintainers for confirmation
Comment #30
bleen commentedThis behavior is precisely the problem. AJAX actions will do a complete form submission but in that case it is often very very bad for the validation to run at all.
Comment #31
valthebaldClassical "bug or feature" dilemma. I can give good reasons to always run validate callbacks, you see it as a bug. Obviously we need a third opinion here
Comment #32
andypostSuppose this issue requires @chx review
Comment #33
valthebald@chx's answer (from IRC):
Comment #34
nerdoc commentedComment #35
agence web coheractio commentedI face the same situation as described in #30 :
When I click on the submit, the submit process is blocked by an "illegal choice" error set on the radio buttons.
How can I prevent this validation to happen?
For the moment, the only solution I've found is to write a form validation function that gets rid of this error.
Thanks
Laurent
Comment #36
jaypanIf you’re seeing the illegal choice detected error, it is a different issue to this one. I’m guessing you’ve added form elements in an Ajax callback.
Comment #37
agence web coheractio commentedThat's the same issue as described in #30
1. Add radio buttons with ajax submit (these radio buttons are set to #required=TRUE)
2. Remove these radio buttons with ajax submit having #limit_validation_errors = []
3. Form gets stuck with "illegal choice" error set on the radio buttons.
In my opinion, this shouldn't be the case : radio buttons shall be removed without form state error.
If this is not bug (as mentionned in #33), I struggle to understand the rationale behind this behavior?
Comment #38
jaypanMy last comment remains. You’re misdiagnosing the issue.
Comment #39
agence web coheractio commentedYou should read before commenting. It always helps...
The bug (or whatever it is called) I describe is precisely caused by the fact that :
which is the title of this issue.
The side effect of that calls is that errors detected during the elements validation (e.g. a required element not set) are preventing to pass the validation process even though they should not be taken into account because of the #limit_validation_errors = [] set on the submit element .
Anyway, I've found a solution on my own to circumvent this "Closed (works as designed)" issue or feature request (or whatever it is called) .
Comment #40
jaypanI did:
Adding/removing/altering elements in Ajax callbacks causes the error you are seeing. You’re misdiagnosing the issue. It’s not related to this topic.