There is no way to make a button element that can use the AJAX functionality

Created on 30 July 2008, over 16 years ago
Updated 19 February 2023, almost 2 years ago

As per this very old forum discussion, creating form element buttons with a type of anything other than type="submit" is not possible as we can see it is written directly into the return value below:

From forms.inc:

/**
 * Theme a form button.
 *
 * @ingroup themeable
 */
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="submit" '. (empty($element['#name']) ? '' : 'name="'. $element['#name'] .'" ') .'id="'. $element['#id'] .'" value="'. check_plain($element['#value']) .'" '. drupal_attributes($element['#attributes']) ." />\n";
}

This code is Drupal 5.9 but also applies to Drupal 6.3.

This code contradicts the Forms API Reference, as well as published print materials as noted in the forum discussion: Forms API Ref: #button_type

This check for #button_type and change to the return value should fix things:

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'];
  }

  $element['#button_type'] = (isset($element['#button_type'])) ? $element['#button_type'] : 'submit';

  return '<input type="'. $element['#button_type'] .'" '. (empty($element['#name']) ? '' : 'name="'. $element['#name'] .'" ')  .'id="'. $element['#id'].'" value="'. check_plain($element['#value']) .'" '. drupal_attributes($element['#attributes']) ." />\n";
}

Does this make sense? If so, I'll roll patches against 5.9 and 6.3.

πŸ› Bug report
Status

Needs review

Version

10.1 ✨

Component
FormΒ  β†’

Last updated 1 day ago

Created by

πŸ‡¨πŸ‡¦Canada Ryan Palmer

Live updates comments and jobs are added and updated live.
  • Needs framework manager review

    It is used to alert the framework manager core committer(s) that an issue significantly impacts (or has the potential to impact) multiple subsystems or represents a significant change or addition in architecture or public APIs, and their signoff is needed (see the governance policy draft for more information). If an issue significantly impacts only one subsystem, use Needs subsystem maintainer review instead, and make sure the issue component is set to the correct subsystem.

  • Needs issue summary update

    Issue summaries save everyone time if they are kept up-to-date. See Update issue summary task instructions.

Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • πŸ‡ΊπŸ‡ΈUnited States smustgrave

    Hiding #18

    #31 does sound like a good approach. Tagging for framework managers for their thoughts.

    Once that's decided the issue summary would need to be updated.

  • πŸ‡¦πŸ‡ΊAustralia larowlan πŸ‡¦πŸ‡ΊπŸ.au GMT+10

    #9 seems to be the way forward here, is this just a docs issue?

  • Status changed to Postponed: needs info almost 2 years ago
  • πŸ‡¦πŸ‡ΊAustralia larowlan πŸ‡¦πŸ‡ΊπŸ.au GMT+10
  • πŸ‡¦πŸ‡ΊAustralia darvanen Sydney, Australia

    @larowlan the documentation states that #buttons don't trigger the submit handler. Do we change the documentation or update the API to meet what seems to be the original intent?

  • πŸ‡¦πŸ‡ΊAustralia larowlan πŸ‡¦πŸ‡ΊπŸ.au GMT+10

    tbh I'm not sure, I don't use #type button very often

  • Status changed to Needs review over 1 year ago
  • πŸ‡³πŸ‡±Netherlands seanB Netherlands

    I don't think #9 fixes the issue. The problem is in the browser. When pressing the enter key, the first input element with type "submit" is triggered, instead of the actual form submit button. We should really stop using type "submit" for AJAX buttons, since they are not the primary form submit button. This is caused by the fact that Drupal\Core\Render\Element\Button always uses "submit" as the button type.

    So we either need to add a new setting to allow changing the button type, maybe a key like #submit_button?

     $form['ajax_example'] = [
       '#type' => 'button',
       '#submit_button' => FALSE,
       '#value' => $this->t('My AJAX button'),
     ];
    

    Or another render element that always uses the button type. Something like #type = 'ajax_button' (although it is not necessarily always going to be used for AJAX stuff).

  • Status changed to Needs work over 1 year ago
  • πŸ‡ΊπŸ‡ΈUnited States smustgrave

    Didn't see a patch to review

    But was previously tagged for issue summary update which I'm sure is still needed. Plus when a patch is there will need a test case

  • πŸ‡¦πŸ‡ΊAustralia darvanen Sydney, Australia

    Thanks @smustgrave :)

    #39: @seanB it would seem at the moment that Drupal's take on an AJAX button is that its sole purpose is to trigger a backend handler on the form, be it the submit handler or a different method (and therefore the advice to simply turn off the submit handler).

    How do we make the case for buttons which don't send anything to the backend at all? I think that would be the easiest one to get support behind. And from there we can talk about how to do it.

    I've lost track of what I was trying to do when I came across this issue.

    Perhaps we could make a contrib module which demonstrates the issue and will give us a measurable indicator of demand (beyond how few concerned people have found this ticket)?

  • πŸ‡³πŸ‡±Netherlands seanB Netherlands

    Well, the list of issues in #31 is a pretty big indicator that people are struggling with problems because of the fact that it is impossible to create an <input type="button"> at the moment. Of course, we could do this in contrib, but that would mean all modules that have AJAX buttons would need a dependency on this new module to solve the issue.

    Adding a flag like #submit_button to the existing button element would probably be the easiest and most developer friendly way to solve this. So I'm hoping this is a thing we could add to core.

  • πŸ‡ΊπŸ‡ΈUnited States smustgrave

    Possible to get the issue summary update or a test case?

  • πŸ‡¬πŸ‡§United Kingdom catch

    I think #submit_button defaulting to TRUE is a good idea here, it would be backwards compatible and less confusing than having two button elements.

    This is a small API addition rather than a bug IMO, so reclassifying as a task. Also re-titled and updated the issue summary.

  • πŸ‡¬πŸ‡§United Kingdom oily Greater London
  • πŸ‡¬πŸ‡§United Kingdom oily Greater London
  • πŸ‡¬πŸ‡§United Kingdom oily Greater London
  • πŸ‡¬πŸ‡§United Kingdom oily Greater London

    I am testing in the browser via the Drupal UI the current 'fix' now committed to the issue fork. I am testing using the 'simple form' in the examples project forms api module.

    With the #submit_button left at default TRUE the html is:
    <input class="button--primary button js-form-submit form-submit" data-drupal-selector="edit-submit" type=β€œsubmit” id="edit-submit" name="op" value="Do Not Submit!">

    With the #submit_button set to FALSE:
    <input class="button--primary button js-form-submit form-submit" data-drupal-selector="edit-submit" type="button" id="edit-submit" name="op" value="Do Not Submit!">

    Note that the class attributes 'js-form-submit' and 'form-submit' are left unchanged. The 'type' attribute IS changed which seems the only requirement for the purposes of this issue. If anyone sees a good reason to change the class attributes please comment!

    Otherwise the task of writing a failing functional test should be straightforward.

  • Pipeline finished with Failed
    5 months ago
    Total: 120s
    #286095
  • πŸ‡¬πŸ‡§United Kingdom oily Greater London

    The Forms functional tests are extensive and it is tricky to work out the best place to put this test. I have arrived at the idea of creating one or two new test forms with only 2 or 3 form elements defined. Then insert a new test function (or 2) in the ElementTest test class and assert that the 'type' attribute contains 'button' or 'submit' using the 'xpath' selector type..

  • Pipeline finished with Failed
    5 months ago
    Total: 159s
    #286237
  • Pipeline finished with Failed
    5 months ago
    Total: 186s
    #286250
  • Pipeline finished with Failed
    5 months ago
    Total: 141s
    #286265
  • Pipeline finished with Failed
    5 months ago
    Total: 161s
    #286267
  • Pipeline finished with Success
    5 months ago
    Total: 418s
    #286282
  • Pipeline finished with Success
    5 months ago
    Total: 608s
    #286302
  • Pipeline finished with Success
    5 months ago
    Total: 571s
    #286521
  • Pipeline finished with Failed
    5 months ago
    Total: 1616s
    #286667
  • Status changed to Needs review 5 months ago
  • πŸ‡¬πŸ‡§United Kingdom oily Greater London

    ElementTest::testFormElements triggers all the tests defined inside ElementTest.php. There is one failing test ElementTest::testFormElementErrors but it is outside the scope of this issue.

    The test created under this ticket ElementTest::testSubmitButtonAttribute is passing.

  • Pipeline finished with Failed
    5 months ago
    Total: 1337s
    #286688
  • Status changed to Needs work 5 months ago
  • πŸ‡ΊπŸ‡ΈUnited States smustgrave

    Left comments on MR.

  • Pipeline finished with Canceled
    5 months ago
    Total: 66s
    #287294
  • Pipeline finished with Canceled
    5 months ago
    #287295
  • Pipeline finished with Success
    5 months ago
    Total: 426s
    #287296
  • Pipeline finished with Failed
    5 months ago
    Total: 521s
    #287341
  • πŸ‡¬πŸ‡§United Kingdom oily Greater London

    For some reason my local phpunit is ignoring the functional test method introduced by the merge request. Troubleshooting this now.

  • Status changed to Needs review 5 months ago
  • πŸ‡¬πŸ‡§United Kingdom oily Greater London
  • Status changed to Needs work 5 months ago
  • πŸ‡¦πŸ‡ΊAustralia darvanen Sydney, Australia

    I'm so happy to see some traction on this and buy-in from @catch. The approach looks good to me, I think we just need to tidy a few things to grease the wheels.

  • Pipeline finished with Canceled
    5 months ago
    #289026
  • Pipeline finished with Failed
    5 months ago
    Total: 648s
    #289028
  • πŸ‡ΊπŸ‡ΈUnited States smustgrave

    Threads about the 80 character wrapping still seem to be needed.

  • Pipeline finished with Failed
    4 months ago
    Total: 175s
    #303395
  • Pipeline finished with Success
    4 months ago
    #303402
  • πŸ‡¬πŸ‡§United Kingdom oily Greater London

    @smustgrave @darvanen I have reacted to the code comments re the 80 character limit. Changing back to Needs review

  • πŸ‡¬πŸ‡§United Kingdom oily Greater London
  • πŸ‡¬πŸ‡§United Kingdom oily Greater London
  • πŸ‡¬πŸ‡§United Kingdom oily Greater London
  • πŸ‡¬πŸ‡§United Kingdom oily Greater London
  • πŸ‡ΊπŸ‡ΈUnited States smustgrave
    1) Drupal\Tests\system\Functional\Form\ElementTest::testFormElements
    Behat\Mink\Exception\ExpectationException: 0 elements matching xpath "//input[@type="button"]" found on the page, but should be 1.
    /builds/issue/drupal-289240/vendor/behat/mink/src/WebAssert.php:888
    /builds/issue/drupal-289240/vendor/behat/mink/src/WebAssert.php:441
    /builds/issue/drupal-289240/core/modules/system/tests/src/Functional/Form/ElementTest.php:161
    /builds/issue/drupal-289240/core/modules/system/tests/src/Functional/Form/ElementTest.php:35
    FAILURES!
    Tests: 1, Assertions: 74, Failures: 1.
    Exiting with EXIT_CODE=1
    

    Shows the test coverage

    Also resolved the threads because they appeared to all be addressed.

    I did not find anything else pending and code looks fine to me.

    Going to mark it.

  • πŸ‡³πŸ‡ΏNew Zealand quietone

    I read the IS, comments and the MR. I think two comments need to be improved. I did one but the other I wasn't sure what to add so setting this to needs work for those comments.

  • πŸ‡¬πŸ‡§United Kingdom oily Greater London

    @quietone I have read the new version of the docblock comment by @trackleft2. It looks good to me. Does it 'tick the boxes' for you too? If so I would like it to be committed in place of my own docblock comment.

  • Pipeline finished with Failed
    about 2 months ago
    Total: 219s
    #367768
  • Pipeline finished with Success
    about 2 months ago
    Total: 561s
    #367778
  • Pipeline finished with Success
    about 2 months ago
    Total: 527s
    #367800
  • πŸ‡¬πŸ‡§United Kingdom oily Greater London
  • πŸ‡ΊπŸ‡ΈUnited States smustgrave

    Believe feedback has been addressed

Production build 0.71.5 2024