On a Drupal 8 site I have a world map where the user can click on a country; a view with content is then loaded with AJAX using a custom module and the following JavaScript.
(function($, Drupal, drupalSettings, window, document) {
Drupal.behaviors.worldmap = {
attach(context, settings) {
console.log('behaviors called');
$('#map-container', context).once('addmap').each( () => {
let map = new InteractiveMap('.interactive-map', (country) => {
let id = settings.worldmap.yearsnids[country];
if(!id) {
id = 0;
}
console.log('id');
let ajax_settings = {
url: '/my_module/ajax/expand/' +
settings.worldmap.ctype + "-infobox/" + id,
};
Drupal.ajax(ajax_settings).execute();
});
map.init();
});
...
I have a custom template for the view where I add a ajax link.
<a href="/my_module/ajax/expand/{{ fields.field_content_type.content|render|striptags|trim }}/{{ fields.nid.content|render|striptags|trim }}" class="button use-ajax">See the project</a>
Clicking that link loads another view with more content. So basically a preview is loaded when the user clicks on a country, and a link in the preview then loads the full content if clicked.
Both the preview and the content (also a view), is loaded from my_module with an AjaxResponse:
namespace Drupal\my_module\Controller;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\ReplaceCommand;
use Drupal\Core\Controller\ControllerBase;
class my_moduleController extends ControllerBase {
public function loadContent($method, $action, $type, $nid) {
$response = new AjaxResponse();
// logic to determine which action and type we want to load
...
$build['view'] = [
'#type' => 'view',
'#name' => $viewname,
'#display_id' => $did,
'#arguments' => [$nid],
];
$response->addCommand(new ReplaceCommand($replaceClass,
$build, ['fadeIn']));
return $response;
}
}
This all works, but the link in the preview only works for the first preview loaded. In every other preview loaded, clicking the link sends the user to the actual ajax-path (eg. mysite.com/my_module/ajax/expand/my_ctype-infobox/the_actual_id), and the content that should have been rendered to the page are displayed like json in a textbox:
[{"command":"settings","settings":{"pluralDelimiter":"\u0003","ajaxPageState":
...
When the page with the map is loaded, and first time the preview is loaded, 'behaviors called' prints to the console - the link to load the full content works. On subsequent times, clicking on a country loads the preview, but behaviors aren't called at all. 'id' gets printed to the console every time I click.
This is the HTML structure:
<div class="interactive-map">
<div id="map-container"></div>
<div class="info-box">
<div class="info-box__content">
<div class="placeholder"></div>
</div>
</div>
</div>
<div class="full-content-wrapper">
<div class="placeholder"></div>
</div>
The preview is loaded into the info-box__content div, which is outside the #map-container.