I am trying to create ajax links in a twig template (not in a form) in Drupal 8 and have run into a strange phenomenon.

I have managed to create a simple link that opens an alert. This works when I place it in my twig template at the very top or bottom of the markup so I know that my router, controller and template are working. However, when I place the exact same code within a twig function it stops working properly. Instead of a pop-up alert, the json is returned but shown on a new page with nothing except a texarea containing the json data. The page has no head info (just empty tags) or any other markup.

I also noticed that placing the link () tag immediately after the opening twig function statement caused the link to not even be rendered on the page.

Json content:

[{"command":"alert","text":"Hello, Bob"}]

So my question is why does this happen and how can I fix it?

My twig file looks like this:

<div class='available'>

<!-- This works -->
<a class="use-ajax" href="/custom_ajax_link/Bob"> open alert for ajax link testing </a>

{% for key, pos in players %}
    <div class="clearfix pos-title">{{ key }}
        <span class="positionCounts">({{ pos|length }})</span>
    </div>
    <div class="clearfix availablePlayers">
        {% for key, player in pos %}

            <!-- This doesn't even show up in the compiled source -->
            <a class="use-ajax" href="/custom_ajax_link/Bob">Details</a>

            <div data-position="{{ player.disp }}" class="player clickable draggable dragValid">

            <!-- This is rendered but doesn't work -->
            <a class="use-ajax" href="/custom_ajax_link/Bob">Details</a>

              <img class="pImage" src="{{ mod_path }}/images/players/{{ key }}.png" title="{{ player.name }}">
            <div class="pPlayerPos hidden">{{ player.nid }}</div>
          </div>
        {% endfor %}
        </div>
      {% endfor %}
    </div>

    <!-- This works -->
    <a class="use-ajax" href="/custom_ajax_link/Bob"> open alert for ajax link testing </a>

</div>

The output html (sample)

<div class='players'>
  <div class='list'>
    <div class='available'>
      <a class="use-ajax" href="/pane_details/234">Details</a>
      <div class="clearfix pos-title">CF<span class="positionCounts">(25)</span></div>
      <div class="clearfix availablePlayers">
        <div data-position="0" class="player clickable draggable dragValid">
          <a class="use-ajax" href="/custom_ajax_link/1">
            <img class="pImage" src="modules/custom/we2018/images/players/33702.png" title="S. AGÜERO">
          </a>
          <div class="pPlayerPos hidden">1</div>
        </div>
        <div data-position="1" class="player clickable draggable dragValid">
          <a class="use-ajax" href="/custom_ajax_link/2">
            <img class="pImage" src="modules/custom/we2018/images/players/34881.png" title="L. SUÁREZ">
          </a>
          <div class="pPlayerPos hidden">2</div>
        </div>

        ...

        <div id="playerDetailsPane" class='details'>
            <div class="detailsTop">
              <img class="detImage" src="modules/custom/we2018/images/players/33702.png">
              <div class="detName"></div>
              <div class="detTeam"></div>
              <div class="detPos hidden">42</div>
            </div>
            <div class="detailsBottom">
              <div class="detAge">Age:</div>
              <div class="detAttack">Attack:</div>
              <div class="detDef">Defense:</div>
              <div class="detFoot">Foot: </div>
              </div>
            </div>
            <div class="moreDetails">More...</div>
        </div>
      </div>
      <a class="use-ajax" href="/custom_ajax_link/Bob"> open alert for ajax link testing </a>
    </div>
  </div>
</div>

My router file:

custom_ajax_link.routing:
  path: '/custom_ajax_link/{pid}'
  defaults:
    _title: 'Custom Ajax Link'
    _controller: '\Drupal\custom_ajax_link\Controller\CustomAjaxLinkController::customAjaxLinkAlert'
  requirements:
    _permission: 'access content'

My Controller file:

<?php
namespace Drupal\custom_ajax_link\Controller;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\AlertCommand;
use Drupal\Core\Controller\ControllerBase;

class CustomAjaxLinkController extends ControllerBase {
  public function customAjaxLinkAlert($pid) {
    # New responses
    $response = new AjaxResponse();
    # Ajax Commands
    $response->addCommand(new AlertCommand('Hello, '. $pid));
    # Return response
    return $response;
  }
}
New contributor
maklad42 is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
  • When you see the json array of the ajax response then ajax.js didn't attach to the use-ajax link. You need to debug this in the browser. Is the HTML produced by Twig valid? Are there script errors? Obviously there is more js code for the player, does it work if you remove the other js code? – 4k4 Dec 7 at 7:19
  • @4k4 As far as I can see, the html is valid. I have added a sample to the post. There are 250 players in total so obviously I can't add everything. – maklad42 2 days ago
  • There are no errors showing in the debugger. After removing all other js, each link was responsive (throbber appeared). However, the results were not updated. – maklad42 2 days ago
  • @4k4 I added a replaceCommand to my controller and noticed that the alert is now returning the correct player name, but the .detName div is not updating because the wrapper (div tag) is also being replaced. How can I just replace the inner text? $response->addCommand(new AlertCommand('Hello, '. $pDetails['name'])); $response->addCommand(new ReplaceCommand("#playerDetailsPane .detName", $pDetails['name'])); – maklad42 2 days ago
  • @4k4 I got the replaceCommand working with a render array. Adding the following js back in broke things again. Any ideas? (function ($, Drupal) { Drupal.behaviors.we2018js = { attach: function (context, settings) { initialIndex(); function initialIndex() { $('.draggable').draggable({ containment: 'document', opacity: .8, zIndex: 10000, appendTo: 'body', cursor: 'move', cursorAt: {top: 15, left: 15}, helper: 'clone' }); } } }; }(jQuery, Drupal)); – maklad42 23 hours ago

Your Answer

maklad42 is a new contributor. Be nice, and check out our Code of Conduct.

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Browse other questions tagged or ask your own question.