Creating an HTMX block using the ctools

Created on 27 February 2025, 3 months ago

Hello,
ο»Ώ
I tried creating an HTMX block using the ctools tool, And place it on the right sidebar through the HTMX loader, First visit to Demo 2 page after clearing cache, Then visit Demo 3 again, Please see the content loaded in the right-hand sidebar, it alway displays Demo 2 content on all pages, How can I do to display the correct data on each page?

Thank you





πŸ’¬ Support request
Status

Active

Version

1.4

Component

Miscellaneous

Created by

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @msn5158
  • This is an HTMX block caching issue, I installed this module blocache β†’ , However, it only applies to Layout Blocks and cannot be applied to HTMX Blocks, Is there any way to clear the HTMX block cache?

  • Hello,

    This is still a very concerning issue, If the content created in the HTMX block is based on the current page context, It will not work as expected, It will always display the content loaded for the first time, When the HTMX block content is first loaded, its corresponding URL (/htmx/blocks/view/{block}) page content will be cached, and then the same content will be displayed on all pages, It does not have a good cache invalidation mechanism, as it does not invalidate the cache based on the current page context or different pages.

    I create a text block β†’ in the HTMX block, load the content into the editor, and then use a text formats and editors with PHP β†’ filter to clear the cache of the HTMX block, It successfully solved this problem, However, another issue was discovered, When I am not loading HTMX block content on a certain page, but directly accessing the HTMX block URL, such as (/htmx/blocks/view/test), It won't display any content because it has not been loaded on a certain page, so there is no relevant page context, Then, when returning to a certain page to refresh and load the HTMX block, It will also not display any content, it is empty, The most crucial thing is that it will affect all pages, and even all visitors will not be able to access the content in the HTMX block, Administrators must flush all caches before they can access it normally, Clearing browser cache by visitors is ineffective, Administrators must flush all caches of website.

  • πŸ‡ΊπŸ‡ΈUnited States fathershawn New York

    It sounds to me like what is needed is that the dedicated render controller for the HTMX block needs to use the context of the requesting page.

  • πŸ‡ΊπŸ‡ΈUnited States fathershawn New York

    And in fact I did that in \Drupal\htmx\Render\HtmxBlockView::build. So now to figure out why is didn't do that for the caching

  • πŸ‡©πŸ‡ͺGermany mxh Offenburg

    Hope I extracted the right code part from \Drupal\htmx\Render\HtmxBlockView::build which currently looks like this:

    /**
       * {@inheritdoc}
       */
      public function build(HtmxBlock $block): array {
        $build = [];
        $currentRequest = $this->requestStack->getCurrentRequest();
        // Verify that this is an HTMX request.
        if (
          $currentRequest instanceof Request
          && $currentRequest->headers->has('HX-Current-URL')) {
          $simulatedContext = Request::create(
            uri: $currentRequest->headers->get('HX-Current-URL'),
            cookies: $currentRequest->cookies->all(),
            server: $currentRequest->server->all(),
          );
          if ($currentRequest->hasSession()) {
            $currentRequest->getSession()->save();
            $simulatedContext->setSession($currentRequest->getSession());
          }
          // Add the simulated request to the top of the stack.
          $parameters = $this->routeMatchingEnhancer->matchRequest($simulatedContext);
          $simulatedContext->attributes->add($parameters);
          unset($parameters['_route'], $parameters['_controller']);
          $simulatedContext->attributes->set('_route_params', $parameters);
          $this->requestStack->push($simulatedContext);
          if ($block->access('view')) {
            $build = $this->renderBlock($block);
          }
          // Remove the simulated context.
          $this->requestStack->pop();
        }
        return $build;
      }
    

    Haven't verified, but maybe there is no cache context handling defined for the special HX-Current-URL header?
    Maybe add a cache context as provided by Drupal\Core\Cache\Context\HeadersCacheContext like this:

    // ...
    $build['#cache']['contexts'][] = 'headers:HX-Current-URL';
    return $build
    

    Also be aware that Page Cache doesn't know of any cache contexts or headers πŸ› Page Cache must respect Vary, otherwise it might serve mismatched responses. Active .

  • πŸ‡ΊπŸ‡ΈUnited States fathershawn New York

    That's the right idea :). When I have time I'll inspect the render array there.

Production build 0.71.5 2024