Score:4

How can I add inline markup to submit buttons?

ua flag

I migrate code from Drupal 7 to Drupal 10, in Drupal 7 I often created buttons with an icon and text like showen aboven:

Drupal 7 code:

$form['submit'] = [
  '#type' => 'submit',
  '#value' => t('<i class="glyphicon glyphicon-share"></i> Register'),
  '#attributes' => ['class' => ['btn-success btn-sm']],
];

When I try to do this in my drupal 10 code, the icon (I replaced the glyphicon by a bootstrap icon and the icon is showen when I use it e.g. in #markup) is not visible. I recognized, that drupal 10 renders '#type' => 'submit' as <input> instead of <button> and I think that this is the reason for this behaviour.

(Not working) Drupal 10 Code:

$form['actions']['submit'] = [
  '#type' => 'submit',
  '#value' => Markup::create('<i class="bi bi-box-arrow-up-right"></i> Register'),
  '#attributes' => ['class' => ['btn-success btn-sm bi bi-box-arrow-up-right']],
];

I was really wondering why this is so complicated in D10, I thought this would be a common task. Is there perhaps a simple option that I missed or has anyone a suggestion how I can add icons to the text of submit buttons like I did it in Drupal 7?

Thank you for your ideas.

leymannx avatar
ne flag
Have you tried `'#type' => 'button'`? https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Render%21Element%21Button.php/class/Button/10
cn flag
I think you'll either need to use `button` as @leymannx mentioned, or use a different styling method - `#value` works with `<button>` because it's a container element, and the value is used as the child markup, but `<input>` is inline, and the value is used for an attribute, which obviously won't respond to CSS. [This thread](https://stackoverflow.com/questions/9376192/add-icon-to-submit-button-in-twitter-bootstrap-2) on SO is for BS2, but has some answers which help to explain the various solutions for newer versions as well as the older ones. Might help to get the creative juices flowing
chris avatar
ua flag
Thank you for your suggestions. @leymannx Unfortunately `'#type' => 'button'` is rendered as `<input>` element, too. I think there are only differences with the submit handlers: `<input data-drupal-selector="edit-submit" type="submit" id="edit-submit" name="op" value=" Register" class="button js-form-submit form-submit btn btn-primary">`
Score:2
ua flag

One possible solution (as showen in the link of @Clive) might be using a html <label>.

The following works for me:

$form['actions']['submit'] = [
  '#type' => 'submit',
  '#prefix' => Markup::create('<label for="edit-submit" class="btn btn-primary"><i class="bi bi-box-arrow-up-right"></i> Register</label>'),
  '#value' => 'Register',
  '#attributes' => ['style' => ['visibility:hidden']]
];

The drupal created button will be hidden and replaced by the label, the drupal submit handler will still be called.

Score:0
cn flag

This is the sort of customisation best done in the theme, and fortunately there's a neat little trick that will help you achieve it, using the '#theme_wrappers' key:

$form['actions']['submit'] = [
 '#type' => 'submit',
 '#value' => $this->t('Register'),
 '#theme-wrappers' => ['input__submit__register_button'],
];

With this setting in the button array the theme layer will, before using the default suggestions, look for a template called 'input--submit--register-button.html.twig', which might contain something like this:

<input{{attributes}}><i class="bi bi-box-arrow-up-right">{{children}}</i>

This technique extends to other elements though for some you will need to use the '#theme' key rather than '#theme_wrappers', and some experimentation may be necessary. (Note that '#theme' expects a string value rather than an array.)

cn flag
`<input>`s can't have children (or closing-tags), so this specific approach wouldn't work, the HTML is invalid. You could theoretically use this approach to wrap it with a `<button>`, which can have children, but there are probably better ways to do that
Alfred Armstrong avatar
cn flag
@Clive I copied this template and tested it locally but admittedly this was in a theme that has radix as a base so it might not be universal. The method for suggesting a template should work, it's just a matter of using the right template to start with and then adapting it.
Alfred Armstrong avatar
cn flag
@Clive I think it's just a matter of removing the closing </input> , I'll edit that out. The system input.html.twig does have {{ children }}, at least in D9.5
Alfred Armstrong avatar
cn flag
@Clive I get what you mean about not being able to inject html into the value attribute, though, and this may not be what the OP wants.
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.