ajax_custom_formatter.rst 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. AJAX Responsive Formatters
  2. ===========================
  3. Some fields need to be responsive. For example, a user might select an analysis or organism to display data from. Drupal developers often use AJAX to rebuild the page based on user input.
  4. Drupal and AJAX
  5. ---------------
  6. Drupal has its own special way of doing AJAX! This is important to ensure that changes are executed in the correct order. You should `read the documentation carefully! <https://api.drupal.org/api/drupal/includes%21ajax.inc/group/ajax/7.x>`_ The Drupal AJAX API works best on forms, and field formatters **are not forms**. Instead, they are `renderable arrays. <https://www.drupal.org/docs/7/api/render-arrays/render-arrays-overview>`_
  7. As such, rather than accepting ``$form`` and ``&$form_state``, they accept ``&$element``, ``$entity_type``, ``$entity``, ``$langcode``, ``$items``, and ```$display``, where ``$element`` is the renderable array.
  8. This means if you want to add an AJAX callback to a field formatter, you need a **separate form function** that gets added in using ``drupal_get_form()``. If you do this, you can build the AJAX as Drupal expects it.
  9. Example form and field
  10. ----------------------
  11. Here's an example form file below: as you can see it's a standard form following Drupal AJAX conventions. We provide a ``rendered_maps`` fieldset with the prefix defining the wrapper (``examplemap-featuremap-organism-selector-wrapper``). This is what we want to re-draw depending on what the user selects.
  12. The selector has specified that wrapper, and the AJAX callback function ``examplemap_organism_featuremap_callback``. We then define that function to simply return the piece of the form that should be rebuilt: the ``rendered_maps`` fieldset!
  13. .. code-block:: php
  14. /**
  15. * AJAX-enabled form for [field formatter name].
  16. */
  17. function tripal_example_map_organism_featuremap_selector_form($form, &$form_state, $select) {
  18. $selected = 0;
  19. // $form_state['values'] will be set if the form has been submitted via AJAX
  20. if (isset($form_state['values']['featuremap_select'])) {
  21. $selected = isset($form_state['values']['featuremap_select']);
  22. }
  23. // We need to provide a container for Drupal AJAX to replace.
  24. // Here we use a fieldset with a set ID which we can refer to below.
  25. $form['rendered_maps'] = [
  26. '#type' => 'fieldset',
  27. '#collapsible' => FALSE,
  28. '#prefix' => '<div id="examplemap-featuremap-organism-selector-wrapper">',
  29. '#suffix' => '</div>',
  30. ];
  31. // This is the element which will trigger AJAX.
  32. $form['rendered_maps']['featuremap_select'] = [
  33. '#type' => 'select',
  34. '#options' => $select,
  35. '#title' => 'Please select a map to view',
  36. '#default_value' => $selected,
  37. '#ajax' => [
  38. // Your Drupal AJAX callback
  39. // which simply returns the form element to be re-rendered.
  40. 'callback' => 'examplemap_organism_featuremap_callback',
  41. // This should be the ID you set above on your container to be replaced.
  42. 'wrapper' => 'examplemap-featuremap-organism-selector-wrapper',
  43. 'effect' => 'fade',
  44. ],
  45. ];
  46. // Check the AJAX submitted values...
  47. $chosen = 0;
  48. if (isset($form_state['values']['featuremap_select'])) {
  49. $chosen = $form_state['input']['featuremap_select'];
  50. }
  51. // If the user chose an option (triggered AJAX).
  52. if ($chosen != 0) {
  53. // Then change the form accordingly...
  54. // Notice that you react to the AJAX change in the form
  55. // not in the AJAX callback.
  56. $mini_form = tripal_example_map_genetic_map_overview_form([], $form_state, $chosen);
  57. $form['rendered_maps']['map'] = $mini_form;
  58. return $form;
  59. }
  60. return $form;
  61. }
  62. /**
  63. * The callback will return the part of the form you want to re-draw.
  64. */
  65. function examplemap_organism_featuremap_callback($form, &$form_state) {
  66. return $form['rendered_maps'];
  67. }
  68. In the field formatter, we simply add this form and put the markup in the element:
  69. .. code-block:: php
  70. /**
  71. * In our Our__field_formatter.inc
  72. */
  73. public function view(&$element, $entity_type, $entity, $langcode, $items, $display) {
  74. // Select choices would be loaded in the base field's load method.
  75. $select = $items[0]['select_choices'];
  76. $form = drupal_get_form('tripal_example_map_organism_featuremap_selector_form', $select);
  77. $content = drupal_render($form);
  78. $element[] = [
  79. '#type' => 'markup',
  80. '#markup' => $content,
  81. ];
  82. return $element;
  83. }