According to the reference,
an action button (a button that does not submit the form).
a form element of type 'button' should produce an <input type='button /> ... but it currently, always, returns a type='submit'.
So I went to the code
( // $Id: form.inc,v 1.128 2006/07/05 )
and changed it to
function theme_button($element) {
//Make sure not to overwrite classes
if (isset($element['#attributes']['class'])) {
$element['#attributes']['class'] = 'form-'. $element['#button_type'] .' '. $element['#attributes']['class'];
}
else {
$element['#attributes']['class'] = 'form-'. $element['#button_type'];
}
return '<input type="'.$element['#type'].'" '. (empty($element['#name']) ? '' : 'name="'. $element['#name'] .'" ') .'value="'. check_plain($element['#value']) .'" '. drupal_attributes($element['#attributes']) ." />\n";
}
( the type="'.$element['#type'].'" used to be type="submit" )
That successfully meant that 'submits' are submits and buttons are buttons ... BUT A whole bunch of things stopped working :-/
Right on node edit for example, (node.module)
$form['preview'] = array('#type' => 'button', '#value' => t('Preview'), '#weight' => 40);
$form['submit'] = array('#type' => 'submit', '#value' => t('Submit'), '#weight' => 45);
Preview is a true button now (and does nothing).
<input type="button" name="op" value="Preview" class="form-submit" />
<input type="submit" name="op" value="Submit" class="form-submit" />
I'm guessing that this can be used to indicate to forms the 'default' submit behaviour ... but is this really being implimented right?
... I won't attach the patch because ... well there's something wrong.
.dan.
Comments
Comment #1
dman commentedBump?
Anyone else want/need/use form 'buttons'?
Comment #2
drupal777 commentedI do, and I think that this (long) thread shows how far I got with it: http://drupal.org/node/67661
Take a look at the example I'm using as my base (the multi-page form example in the handbook) and note how the button is constructed that does the "back" action. I think that the hook is in form_alter.
But when all is said and done, there really is a fine line difference between a classic "submit" and "something else". Since we are dealing with a web server and a web client (browser) there just isn't very much that clicking on a button can do other than "go to the server and report something to that server and then wait for a response".
In my case, I wanted to hit that button and have it create the equivalent of a separate process to do some sort of work. Something that would make perfect sense if it were a link that opened a new window pointed at a new address. But I don't want to open a new window. I just want to do something other than submit the data that has been collected so far. As I state in the other thread, whatever I want to do, it does NOT involve submitting all of the data collected and therefore it should not include validating that data (and displaying all of the error messages associated with any data validation code that might otherwise be contained in the mdoule).
Another variation on this them is an AJAX/javascript combination. Again, I definitely want the server involved, and I need it to be server-side code that executes, not client side javascript.
I hope you get an answer, because I think that the answer to your inquiry is also the answer I need to do what I want to do.
Comment #3
chx commentedyou are free to define any element you want in a contrib module, that's what hook_elements is for. this won't change in core. a document clarification might be in order.
Comment #4
dman commentedFair enough. I have no problem implimenting it as it needs to be.
So... if there's to be no distinction between array('#type'=>'button') and array('#type'=>'submit') , button should be removed altogether. I don't think we need to propogate PHP-like synonyms.
In HTML, [INPUT type='button'] and [INPUT type='submit'] are distinctly different things. For the form render to not honor that leads to confusion.
Granted, button used to be pretty pointless, but whether you use it or not, if it's gonna be available, it should be implimented correctly.
YET, as I saw in lots of core, folk are using 'button' where they should be using 'submit'.
OK, I'll find my own odd work-arounds, possibly implimenting lotsa little custom widget buttons for different tasks isn't such a bad idea at all...
Comment #5
darren ohThe button element is already in core. I would like to know what chx means by a document clarification. This is to all appearances just a bug. Looking at theme_submit(), it appears that submit was intended to be a sub-type of the button element, not the only type.
Since this bug makes button and submit synonymous, the fix is simple. The intended behavior of all current buttons would be preserved by replacing
'#type' => 'button'with'#type' => 'submit'and['#type'] = 'button'with['#type'] = 'submit'wherever they appear.Comment #6
dman commentedThe actual fix/repair to expected behaviour is simple, yes.
The problem is the follow-on effect to all the other contributed modules that until now have been using 'button' incorrectly as a synonym for 'submit' (due to following the lead set in the docs/examples even) and would mysteriously stop working were this fix applied.
Comment #7
darren ohYes, too late to fix for Drupal 6. But it should be on the agenda for Drupal 7.
Comment #8
heine commentedI fail to understand the bug here.
Should read somewhat like: a button that submits the form back to Drupal, where it is validated. The forms submit handler is not invoked.
There is no 1:1 relationship between form api types and HTML input elements, nor is there a need for such a mapping.
Comment #9
darren ohIf someone can verify that there actually is such a difference, I would like to see it accurately documented. At the moment it just confuses people like me who are looking for something else.
Comment #10
darren ohI can now explain the difference. While
'#type' => 'button'and'#type' => 'submit'produce identical HTML output, the Form API keeps track of which is which based on the button's ID. The form's submit function will not be run for'#type' => 'button'. Instead, the form will be modified if required and reloaded.Comment #11
darren ohFor anyone who's interested, form_builder is the function that determines whether the button pressed should cause the submit function to run.
Comment #12
darren ohComment #13
darren ohFixed.
Drupal 5: #81929
HEAD: #81931
Comment #14
(not verified) commentedComment #15
Ryan Palmer commentedDarren Oh, I'm having trouble understanding your reversal of positions from #5 to #12 on this issue. I understand the implications of such a change to this core function, but at the end of the day type="button" is still a valid attribute and input is a html element that is not fully supported without making a hack in a module somewhere (hook_elements). I have a legitimate need for a <input type="button" button that does not submit and it seems many others do as well.
Could readers of the Forms API docs not be forgiven for jumping to the conclusion that #button_type (with default 'submit') has direct relevance to the input "type" attribute, which also currently defaults to 'submit'? I'm reactivating this issue because the documentation is not reflective of the fact that the naming of the #button_type is highly misleading. It seems those in a higher pay grade have already kaboshed the notion of fixing the actual bug(s).
Would it be clearer if:
a) a disclaimer was included in the forms api docs to indicate that #button_type has nothing to do with the input "type" attribute?
b) #button_type was renamed to something else so that this confusion is prevented?
Shooting in the dark here.
Comment #16
darren ohI don't know if there really is a #button type in the new Forms API. If there is, it's no longer necessary. The entire reference needs to be updated, as do most of the Drupal 6 API docs.
Comment #17
betz commentedComment #18
Anonymous (not verified) commentedHi,
Seems there are so many talking . what about a post on a working solution for drupal 5, 6 , 7 to have a button that does not default to submit without so many hacks
Thanks
Comment #19
heine commentedDarren Oh changed the documentation to expand on the "does not submit the form"-confusion.
You can use #type markup to add arbitrary HTML to a form.
Comment #20
chx commentedComment #22
damien_vancouver commentedI found a great workaround for this in Drupal 7, thanks to This StackOverflow question. To quote from the answer there:
You can use:
To disable the "submit" step.
If you only want to disable the "validate" step, use:
This appears to be contrary to what the handbook page Howto: Taming the Form Buttons. has to say. I suspect that this behavior may have changed for Drupal 7?
Anyway, it worked great for me when I added both in there. My use case is I added a button in hook_form_alter, which is supposed to fire off an #ajax callback. So obviously I don't want it validating nor do I want it submitting the form. I first tried adding a button with #type 'markup', but that technique does not allow you to use '#ajax' as well.
Comment #23
Rory commentedSolution by @damien_vancouver at #22 follows expected behaviour but it's just not working for me, when clearly it should.
I've tried as plain a form as I can get and I'm confident enough that this isn't a support issue to do with me, but a bug of some sort.
I'm running Drupal 7.15 and sure enough as the issue is titled... form #type 'button' does not work as advertised - it's always a submit.
Comment #24
heine commentedIf you suspect a bug in Drupal 7, please open a new issue with sufficient information.
The documentation has been amended; the original issue is fixed.
Comment #25
Rory commentedApologies. This is all a bit confusing. The solution at #22 seemed to steer away from the solution given at HowTo: Taming the form buttons but that solution given at HowTo: Taming the form buttons worked for me. I don't know.
The button element's #type is still always 'submit' and I gather this isn't an issue. But to prevent a button from submitting the form however, this is the solution that worked for me:
Comment #26
Rory commentedCross-post!
Comment #28
parveroshan commented#25 works perfect for me...