Problem/Motivation

An #htmx render array key will make it much easier to add interactivity to elements.
We have decided on a facade pattern to manipulate attributes and headers properties and directly apply them to the render array.

Steps to reproduce

Without such a key and a process callback to process #3524030: Provide a factory object for HTMX headers and attributes and move attributes and headers into a final location, developers would need to do that on each element that is enhanced.

Proposed resolution

This issue depends on #3524030: Provide a factory object for HTMX headers and attributes so there is no issue fork yet. Here's the plan and suggested code:

Add a process callback to each element's ::getInfo method.

      '#process' => [
        [static::class, 'processHtmxElement'],
      ],

Here's the static method we will add to RenderElementBase

/**
   * @param mixed[] $element
   *   The render array for the element.
   *
   * @return mixed[]
   *   The modified array with HTMX library attachments, if appropriate.
   */
  public static function processHtmxElement(array $element): array {
    $processed = $element['#htmx_processed'] ?? FALSE;
    // Skip already processed elements.
    if ($processed) {
      return $element;
    }
    // Initialize #htmx_processed, so we do not process this element again.
    $element['#htmx_processed'] = FALSE;

    // Nothing to do if there are no HTMX settings.
    if (empty($element['#htmx']) || !($element['#htmx'] instanceof HtmxInterface)) {
      return $element;
    }
    $htmx = $element['#htmx'];

    // Process operations;
    if ($htmx->hasOperations()) {
      $htmx->processOperations();
    }

    // Attach HTMX and integration javascript.
    $element['#attached']['library'][] = 'core/drupal.htmx';
    // Consolidate headers.
    if ($htmx->headers->count() !== 0) {
      $element['#attached']['http_header'] = $element['#attached']['http_header'] ?? [];
      $element['#attached']['http_header'] = NestedArray::mergeDeep($element['#attached']['http_header'], $htmx->headers->toArray());
    }
    if ($htmx->attributes->count() !== 0) {
      // Consolidate attributes.
      $element['#attributes'] = $element['#attributes'] ?? [];
      $element['#attributes'] = AttributeHelper::mergeCollections($element['#attributes'], $htmx->attributes);
    }

    // Indicate that HTMX processing was successful.
    $element['#htmx_processed'] = TRUE;
    return $element;
  }

Remaining tasks

Finish blocking issues.
Add the process callback to RenderElementBase.
Add the callback to the #process key in the ::getInfo method for every element.

User interface changes

None

Introduced terminology

None

API changes

None

Data model changes

None

Release notes snippet

Comments

fathershawn created an issue. See original summary.

fathershawn’s picture

fathershawn’s picture

Issue tags: +HTMX initiative
fathershawn’s picture

Title: Define and process an #htmx render array key » [PP-3] Define and process an #htmx render array key
Status: Active » Postponed
fathershawn’s picture

Issue summary: View changes
Status: Postponed » Closed (won't fix)
fathershawn’s picture