If I load a node via AJAX and insert it into the page, the flag link that gets inserted with it makes a standard POST request and then redirects me away from the current page rather than making the POST request via Ajax.

Comments

websign.cz’s picture

I managed to get this working by hooking the flagLink.attach behavior in a success callback of my AJAX call. Like this:

$.getScript('/sites/all/modules/flag/theme/flag.js', function() {			
 Drupal.behaviors.flagLink.attach(document);		
});
Renee S’s picture

I had this problem with flags in a view: if the initial view result is empty, then the filter is changed via AJAX and there are results, the flagLink isn't attached properly to the new results. Adding this snippet to my "no results" fixed the problem: thanks, @websign.cz

eta: clarity

shabana.navas’s picture

Issue summary: View changes
Status: Active » Reviewed & tested by the community
joachim’s picture

Status: Reviewed & tested by the community » Active

There's no patch here!

shabana.navas’s picture

I meant this snippet:

$.getScript('/sites/all/modules/flag/theme/flag.js', function() {
Drupal.behaviors.flagLink.attach(document);
});

Seems like #2 tested this and confirmed it works.

Renee S’s picture

Shabana, the "Reviewed & tested by the community" (RTBC) status has a particular meaning for Drupal.org -- it means that there is a patch to the module that has been RTBC'd. This is just an informative code snippet, and there's nothing for the maintainer to do to the module that required open-source input from users to test or perfect. So the status wouldn't be changed (the same applies to "Needs review", if there's a patch for the maintainer to check out and comment on, or "Needs work" if the patch isn't quite right yet.)

This is listed as a bug report, though, which it might still be -- the code is a great workaround, but the problem is still that the attachBehaviors() in the module isn't working when there's an AJAX callback. So I think we should leave this open as a bug report nevertheless.

shabana.navas’s picture

@Renee S, gotcha, thanks. But in regards to your comment in #2:

if the initial view result is empty, then the filter is changed via AJAX and there are results, the flagLink isn't attached properly to the new results.

Is this really just a flag links issue? Wouldn't this happen to any ajaxified link on that exposed filter form, as it has been loaded via ajax. If you take a look this link, isn't it talking about the same thing?

Also, the user that posted the initial issue. It basically talks about the same thing, any ajax loaded form won't have behaviors working on form elements that have the #ajax property until you explicitly give it the javascript settings like this:

  //Retrieve the HTML generated from the $form data structure.
  $html = drupal_render(drupal_get_form('myform'));

  $javascript = drupal_add_js(NULL, NULL);
  $settings = FALSE;

  if(isset($javascript['settings']))
  {
    $settings = '<script type="text/javascript">jQuery.extend(Drupal.settings, ' .
    drupal_json_encode(call_user_func_array('array_merge_recursive', $javascript['settings']['data'])) .
    ');</script>';
  }

  //Add the settings to the form
  $html .= $settings;

  //Print the output
  print $html;

So would we really need to do anything to the flag as it applies to all ajax links on an ajax loaded form? Please take a look at this issue for any further clarification on this and let me know if it has fixed anything.

joachim’s picture

As far as I know, the whole Drupal JS Behaviors system is meant to prevent this sort of problem.

One the one hand, bits of JS functionality declare themselves as behaviours.
On the other, things that load in new content via AJAX have to call the behaviour system to make all behaviours re-attach.

So we shouldn't need a one-off call to Drupal.behaviors.flagLink.attach(document) -- if it's done properly, all should be re-attached.

(Bear in mind though this is just stuff I've picked up here and there -- I am far from being a JS expert!!!)

edtse88’s picture

I'm new to Drupal and my coding skills are very weak. Where exactly do I put the above code snippet to get this working?

Thanks!

gbohara’s picture

#5 worked perfectly for me!

edtse88...

You should be able to identify from where your ajax request is made. If you can Identify the file and the callback function, you can simply copy and paste the code at #5 in your callback function.

imclean’s picture

The issue I'm seeing is with anonymous users using an ajax view with exposed filters. In fact, flag.js isn't being loaded at all.

To get around it, I copied the URL of a "Flag" link, added "&has_js=1" to the end of it then pasted it in the address bar of a new tab.

After refreshing the original page/view then subsequent flag links will work.

It's odd, adding "add_js=1" causes flag.js to load, but loading flag.js is supposed to add has_js=1.

imclean’s picture

Ok, the problem seems to be using drupal_add_js() in template_preprocess_flag(). This doesn't appear to work at all with ajax so I suspect it's the wrong place for it.

To test, add the following line to hook_node_view() (or anywhere else relevant to your page):

drupal_add_js(drupal_get_path('module', 'flag') . '/theme/flag.js');

The question now is where should the js be loaded. There's a discussion in another issue: #2288085: JS not loaded on cached blocks

hellbrus’s picture

You can call this Drupal.attachBehaviors($(context)); in Ajax succesfull callback.

ZalemCitizen’s picture

#13 is working like a charm.
I just put it in a $(document).ajaxComplete() I was already using in a custom module JS.

Thanks hellbrus

handkerchief’s picture

Could someone help me with this? I load new nodes over a controller with ajax, like this example:

https://drupal.stackexchange.com/a/231198

But the flag links in the ajax-loaded nodes doesn't appear. Someone in the stackexchange comments refer to this issue.

Question: Where exactly in the JS-file do I have to execute which code?

My JS-File:

(function ($, Drupal) {
  Drupal.behaviors.loadNodes = {
    attach: function (context, settings) {

      $('#block-views-block-loadnodes-block-2', context).once('loadNodes').each(function () {

        $('.loadnodes-btn').on('click', function () {
          let $this = $(this);
          if (!$this.hasClass('loaded')) {
            let dataId = $this.data('id');
            let $element = $this.next('.collapse').children('.card');
            $element.load('/path-to-controller/load-node' + dataId, function () {
              $this.addClass('loaded');
            });
          }
        });

      });
    }
  };
})(jQuery, Drupal);
handkerchief’s picture

Version: 7.x-2.0-beta6 » 8.x-4.x-dev
handkerchief’s picture

Ok I get it. I have to render the nodes in the controller with renderRoot() and not only with render(). If so, the flag links appear correctly.

b_sharpe’s picture