Generando <button type = "submit"> con el formulario API

12

Tengo una forma muy temática para integrar, cuya estructura se muestra a continuación. Estoy casi allí en su mayor parte, excepto por el envío.

 <form action="#">
   <fieldset>
     <legend>Authentification</legend>
       <label for="email">Courriel*</label>
       <input type="text" name="email" id="email">
       <label for="password">Mot de passe*</label>
       <input type="password" name="password" id="password" class="last">
       <a href="#" title="Mot de passe oublié?" class="clearfix">Forgot password?</a>
       <button type="submit" class="clearfix"><span>Login</span></button>
   </fieldset>
 </form>

He intentado muchas combinaciones diferentes, resulta que button_type no tiene efecto en el núcleo. Así que usé este truco , esperando que solucionara mi problema. Por desgracia, solo cambia el atributo 'type' (obviamente), y no el elemento en sí. El tipo de botón puede contener otros elementos, en este caso, el espacio es necesario para mantener una imagen de fondo, debe estar en un espacio para estirarse ya que el texto en el botón es dinámico.

¿Alguien tiene idea de cómo puedo generar la siguiente línea de marcado utilizando el formulario API?

<button type="submit" class="clearfix"><span>Login</span></button>
Stefgosselin
fuente
Para Drupal 8, el botón de envío se convertirá <botton type="submit">, consulte drupal.org/node/1671190
Philipp Michael el

Respuestas:

12

En D7 recomendaría:

$form['custom-form'] = array(
  '#prefix' => '<button type="submit">',
  '#suffix' => '</button>',
  '#markup' => '<span>' . t('Login') . '</span>',
);

De esa manera, puede reemplazar el #markup en una función alter más tarde si es necesario, sin tener que reconstruir el botón HTML.

tim.plunkett
fuente
Este método no admite autocompete.
Peter Lozovitskiy
17

Además, en caso de que alguien tenga el mismo problema que yo: al usar el truco #markupo #prefix/ #suffixen el actionsgrupo de un formulario , la función de devolución de llamada de envío no se llamará en absoluto , a menos que haya un submitelemento de tipo presente. Mi solución fue así:

$form['actions']['submit'] = array
(
    '#type' => 'submit',
    '#value' => '',
    '#attributes' => array( 'style' => array( 'display: none' )), // hide the input field
    '#submit' => array( 'my_callback_for_the_form_submit' ),
    '#prefix' => '<button type="submit" class="btn btn-primary">Add <i class="fa fa-plus-square-o">',
    '#suffix' => '</i></button>',
);

De esa manera, puede usar HTML personalizado para enviar grupos de acciones.

Óscar Gómez Alcañiz
fuente
Esta fue la mejor respuesta dada ...
Pratip Ghosh
5

Para agregar alguna etiqueta personalizada, puede usar los siguientes fragmentos:

// Drupal 6.
$form = array();

// Other elements.

$form['custom-form'] = array(
    '#value' => '<button type="submit" class="clearfix"><span>Login</span></button>',
);
// Drupal 7.
$form = array();

// Other elements.

$form['custom-form'] = array(
    '#markup' => '<button type="submit" class="clearfix"><span>Login</span></button>',
);
Shoaib Nawaz
fuente
Esto realmente no funcionó, pero me llevó a probar '#markup' en lugar de #value, y eso funcionó. Gracias hermano, lo aprecio.
stefgosselin
1
No informó sobre su versión de Drupal. #value es para Drupal6. #markup introducido en Drupal 7
Shoaib Nawaz
Si amigo, mi mal. Debería haber mencionado el número de versión.
stefgosselin
2

Solo para completar, publicaré una solución alternativa que implica anular theme_button(tomada de esta publicación de blog )

Primero agregue un buttontypeatributo al elemento de formulario:

$form['submit'] = array (
    '#type' => 'submit',
    '#buttontype' => 'button',
    '#value' => 'Search',
);

Y luego anular el botón de tema:

/**
 * Override of theme_button().
 *
 * Render the button element as a button and the submit element as an input element.
 */
function MYTHEME_button($variables) {
  $element = $variables['element'];
  $element['#attributes']['type'] = 'submit';

  element_set_attributes($element, array('id', 'name', 'value'));  

  $element['#attributes']['class'][] = 'form-' . $element['#button_type'];
  if (!empty($element['#attributes']['disabled'])) {
    $element['#attributes']['class'][] = 'form-button-disabled';
  }

  if (isset($element['#buttontype']) && $element['#buttontype'] == 'button') {
    $value = $element['#value'];
    unset($element['#attributes']['value']);
    return '<button' . drupal_attributes($element['#attributes']) . '>' . $value . '</button>';
  }
  else {
    return '<input' . drupal_attributes($element['#attributes']) . ' />';
  }
}

Sin embargo, esto crea problemas si hay más de un botón en el formulario, ya que Drupal no puede detectar en qué botón se ha hecho clic.

Esto se puede solucionar agregando una #after_builddevolución de llamada al formulario:

$form['#after_build'][] = 'mymodule_force_triggering_element';

Y luego en la función after build:

function mymodule_force_triggering_element($form, &$form_state) {
  if (isset($form_state['input']['submit'])) {
    $form_state['triggering_element'] = $form['submit'];
  } elseif (isset($form_state['input']['other_button'])) {
    $form_state['triggering_element'] = $form['other_button'];
  }
  return $form;
}
Víspera de felix
fuente
1

Intenté la respuesta de Óscar Gómez Alcañiz pero mi formulario aún no se había enviado. Como solución alternativa, alteré su solución para que la entrada se ubicara sobre la parte superior del botón pero fuera transparente:

$form['actions']['submit'] = array (
    '#type' => 'submit',
    '#value' => '',
    '#attributes' => array( 'style' => 'position: absolute; left: 0; right: 0; top: 0; bottom: 0; border: none; opacity: 0; width: 100%;'), // put input field over the top of button and make transparent
    '#prefix' => '<button type="submit" class="btn btn-primary">Add <i class="fa fa-plus-square-o">',
    '#suffix' => '</i></button>',
);

De esta forma, input[type="submit]se hace clic en lo real y se activa la acción, pero el botón

Probablemente sea una buena idea poner todo ese CSS en una hoja de estilo en la vida real, pero solo coloque la etiqueta de estilo en línea aquí como ejemplo.

Víspera de felix
fuente
0

Así es como lo logro en Drupal 8. Básicamente, creo una nueva sugerencia de tema para poder anular el botón con un archivo de ramita personalizado.

Agregue este código dentro de su archivo mythemename.theme:

/**
 * Add twig suggestions for input elements.
 *
 * If a form api element has a data-twig-suggestion attribute, then allow twig
 * theme override, add to suggestions.
 *
 * @param array $suggestions
 *   Current list of twig suggestions.
 * @param array $variables
 *   Every variable of the current element.
 */
function mythemename_theme_suggestions_input_alter(&$suggestions, array $variables) {
  $element = $variables['element'];

  if (isset($element['#attributes']['data-twig-suggestion'])) {
    $suggestions[] = 'input__' . $element['#type'] . '__' . $element['#attributes']['data-twig-suggestion'];
  }
}

En su código donde sea que cree su formulario, agregue un atributo 'sugerencia de ramita de datos' a su botón de envío:

$form['submit'] = [
      '#type' => 'submit',
      '#value' => t('Submit') . ' >',
      '#attributes' => [
        'data-twig-suggestion' => 'button',
      ],
    ];

Ahora, si tiene habilitada la depuración de ramitas y verifica la fuente html de su botón en el sitio, verá una nueva sugerencia de ramitas:

<!-- FILE NAME SUGGESTIONS:
   * input--submit.html.twig
   * input--submit--button.html.twig
   x input.html.twig
-->

Ahora puede crear un archivo input - submit - button.html.twig (lo coloco en mythemename / templates / form_elements pero puede colocarlo en otro lugar si lo desea):

<button{{ attributes }} type='submit'>
    <span class="great-success">Submit</span>
</button>
usuario33560
fuente
-3

La forma más correcta es:

$form['submit'] = array(
  '#type' => 'button',
  '#value' => '<span>Login</span>',
);

Produce HTML válido como este:

<button value="&lt;span&gt;Login&lt;/span&gt;" type="submit">
    <span>Login</span>
</button>

... y este método no frena el autocompletado y otras características.

Peter Lozovitskiy
fuente
1
No devuelve una <button>etiqueta, al menos en D7. La última línea de theme_button()in include / form.inc esreturn '<input' . drupal_attributes($element['#attributes']) . ' />';
daniels
¿Podrías volver a verificar? Copié este código de mi módulo personalizado de trabajo.
Peter Lozovitskiy
Si funciona para usted, significa que ha anulado theme_button en un tema o módulo personalizado. Daniels tiene razón.
Felix Eve
@FelixEve, ¡correcto! He anulado el botón en la función personalizada. ¿Hay algún otro método para hacer esto sin una función personalizada?
Peter Lozovitskiy
Este hilo tiene una buena descripción de todos los métodos disponibles.
Felix Eve