0

The block_ajax module defines a behavior in its module:

https://git.drupalcode.org/project/block_ajax/-/blob/8.x-1.x/js/refresh_ajax_block_command.js

I want to initiate this call every 60 seconds so the contents of the block can refresh if there is new data from my own script file.

I tried two ways.

The first way I tried was setting up a route for a simple controller that returned an AjaxResponse:

  public function execute() {
    $response = new AjaxResponse();
    $response->addCommand(new RefreshBlockAjaxCommand('.my_block'));
    return $response;
  }

Hitting the route with Drupal.ajax results in 'context.querySelectorAll is not a function', but it appears that the block is replaced (but missing the block wrapper around it, oddly enough, which probably won't work calling it over and over).

The second way is I tried to call it from the browser console with Javascript, but I can't figure out between this answer and the linked Javascript file at the top of the question what to call.

Trying to loop the element and attachBehaviors results in this:

enter image description here

2 Answers 2

1

Turned out to be a couple of things.

One, I was getting the querySelectorAll error because the Block being rendered was being rendered with a theme and custom template file, which was missing an outer div. The first tag it was seeing was a <style> tag, and breaking on that.

Second, the block_ajax module seems buggy and not fit for refreshing on intervals.

I wound up removing the library that module attaches (from the original question), copying that, and attaching that to my block with two key changes:

Instead of .replaceWith I use .html to preserve the outer Block tags (or they get lost, and the next Ajax command will fail):

// Compose a new block content, replacing the old one
// with it.
var $newBlock = $(data.content);
$block.html($newBlock);

Then, I added this to the file, to initiate a check every 30 seconds with Ajax:

  // Check every 30 seconds if there is a notification.
  setInterval(refresh, 30000);

  function refresh() {
    Drupal.ajax({url: '/api/v1/auth/refresh'}).execute();
  }

Which uses the same service that the block does to read/check an external service for auth state and cookie updates.

Wanted to note that various forms of Drupal.attachBehaviors(context, drupalSettings); did not seem to do anything at all. Perhaps its something wrong in the block_ajax module. It was not returning any errors, but also not refreshing the display.

1
  • "Instead of .replaceWith I use .html to preserve the outer Block tags (or they get lost, and the next Ajax command will fail):" Thanks, this was the key. I've opened an issue: drupal.org/project/block_ajax/issues/3351439 Commented Apr 4, 2023 at 1:52
0

Hitting the route with Drupal.ajax results in 'context.querySelectorAll is not a function.

This happens when Drupal.attachBehaviors() is passed a jQuery object. It expects an HTML string. So if you are doing this:

var element = $(".some_element");
Drupal.attachBehaviors(element);

You change it to:

$(".some_element").each(function () {
  Drupal.attachBehaviors($(this).eq(0));
});
9
  • Just tried that, I still get Uncaught TypeError: context.querySelectorAll is not a function Commented Jun 3, 2020 at 0:18
  • Doing this does in the console does not throw an error, but the AJAX doesn't fire: Drupal.attachBehaviors(element.get(0), drupalSettings) Commented Jun 3, 2020 at 0:32
  • It depends on what you mean by 'ajax doesn't fire', but this will not prevent ajax from firing. Commented Jun 3, 2020 at 0:42
  • It does not trigger the events of this other modules defined behavior: git.drupalcode.org/project/block_ajax/-/blob/8.x-1.x/js/… - no network activity or anything. Essentially I want this block to be refreshed every 60 seconds, instead of once per page load. Commented Jun 3, 2020 at 0:45
  • Are you sure you're passing the correct element? Run console.log() on element.get(0) and see if the elements that are supposed to have the ajax attached are contained in the returned value. Commented Jun 3, 2020 at 0:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.