Skip to main content
Tweeted twitter.com/StackDrupal/status/1560099241242103808
added 3359 characters in body
Source Link

EDIT

For those wondering how to do the same thing, look into what the accepted response mentions about altering the route, because you basically need to overwrite how flag does its job and add your code as an extension of it.

So, I have a RouteSubscriber.php file with the following

namespace Drupal\my_module\Routing;

  use Drupal\Core\Routing\RouteSubscriberBase;
  use Symfony\Component\Routing\RouteCollection;

  /**
   * Listens to the dynamic route events.
   */
  class RouteSubscriber extends RouteSubscriberBase {

    /**
     * {@inheritdoc}
     */
    protected function alterRoutes(RouteCollection $collection) {
      // We need to take control of the default methods for the Flag controller so that we can hook into it's actions and add our own
      if ($route = $collection->get('flag.action_link_flag')) {
        $route->setDefault('_controller', 'Drupal\my_module\Controller\FlagController::flag');
      }
      if ($route = $collection->get('flag.action_link_unflag')) {
        $route->setDefault('_controller', 'Drupal\my_module\Controller\FlagController::unflag');
      }
    }
  }

Then I have a FlagController.php with code such as

namespace Drupal\my_module\Controller;

use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException;
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\flag\FlagInterface;
use Drupal\flag\Controller\ActionLinkController;

/**
 * Controller responses to flag and unflag action links.
 *
 * The response is a set of AJAX commands to update the
 * link in the page.
 */
class FlagController extends ActionLinkController {
  /**
   * Performs a flagging when called via a route.
   *
   * @param FlagInterface $flag
   *   The flag entity.
   * @param int $entity_id
   *   The flaggable entity ID.
   *
   * @return AjaxResponse|null
   *   The response object, only if successful.
   **/
  public function flag(FlagInterface $flag, $entity_id) {
    $response = parent::flag($flag, $entity_id);
    // The line above means your code still does what Flag needs to do, so you need to keep this in, or you'll stop flag working
    
    // Now you can add your own commands based on this link, like below
    https://www.drupal.org/docs/drupal-apis/ajax-api/core-ajax-callback-commands
    $response->addCommand(new EntityAddCommand($foo, $bar, $baz));

    //'EntityAddCommand' is something I wrote in my own javascript function

    return $response;
  }

  /**
   * Performs a unflagging when called via a route.
   *
   * @param FlagInterface $flag
   *   The flag entity.
   * @param int $entity_id
   *   The flaggable entity ID.
   *
   * @return AjaxResponse|null
   *   The response object, only if successful.
   **/
  public function unflag(FlagInterface $flag, $entity_id) {
    $response = parent::unflag($flag, $entity_id);

    //.... etc, do your own commands for unflagging

    return $response;
  }

EDIT

For those wondering how to do the same thing, look into what the accepted response mentions about altering the route, because you basically need to overwrite how flag does its job and add your code as an extension of it.

So, I have a RouteSubscriber.php file with the following

namespace Drupal\my_module\Routing;

  use Drupal\Core\Routing\RouteSubscriberBase;
  use Symfony\Component\Routing\RouteCollection;

  /**
   * Listens to the dynamic route events.
   */
  class RouteSubscriber extends RouteSubscriberBase {

    /**
     * {@inheritdoc}
     */
    protected function alterRoutes(RouteCollection $collection) {
      // We need to take control of the default methods for the Flag controller so that we can hook into it's actions and add our own
      if ($route = $collection->get('flag.action_link_flag')) {
        $route->setDefault('_controller', 'Drupal\my_module\Controller\FlagController::flag');
      }
      if ($route = $collection->get('flag.action_link_unflag')) {
        $route->setDefault('_controller', 'Drupal\my_module\Controller\FlagController::unflag');
      }
    }
  }

Then I have a FlagController.php with code such as

namespace Drupal\my_module\Controller;

use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException;
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\flag\FlagInterface;
use Drupal\flag\Controller\ActionLinkController;

/**
 * Controller responses to flag and unflag action links.
 *
 * The response is a set of AJAX commands to update the
 * link in the page.
 */
class FlagController extends ActionLinkController {
  /**
   * Performs a flagging when called via a route.
   *
   * @param FlagInterface $flag
   *   The flag entity.
   * @param int $entity_id
   *   The flaggable entity ID.
   *
   * @return AjaxResponse|null
   *   The response object, only if successful.
   **/
  public function flag(FlagInterface $flag, $entity_id) {
    $response = parent::flag($flag, $entity_id);
    // The line above means your code still does what Flag needs to do, so you need to keep this in, or you'll stop flag working
    
    // Now you can add your own commands based on this link, like below
    https://www.drupal.org/docs/drupal-apis/ajax-api/core-ajax-callback-commands
    $response->addCommand(new EntityAddCommand($foo, $bar, $baz));

    //'EntityAddCommand' is something I wrote in my own javascript function

    return $response;
  }

  /**
   * Performs a unflagging when called via a route.
   *
   * @param FlagInterface $flag
   *   The flag entity.
   * @param int $entity_id
   *   The flaggable entity ID.
   *
   * @return AjaxResponse|null
   *   The response object, only if successful.
   **/
  public function unflag(FlagInterface $flag, $entity_id) {
    $response = parent::unflag($flag, $entity_id);

    //.... etc, do your own commands for unflagging

    return $response;
  }
Source Link

Custom AJAX Response not firing on Flag action

I'm trying to run custom javascript functions at the same time as people interact with certain flags on my site, I have followed this tutorial on how to respond to both Flag/Unflag actions, and this site for how to setup the custom ajax responses, except it just doesn't appear to be able to combine the two

The code inside my FlagSubscriber.php file (from the first tutorial link) looks like the below

class FlagController implements EventSubscriberInterface {

    public function onFlag(FlaggingEvent $event) {    
      dpm('Test Text');

      $response = new AjaxResponse();
      $response->addCommand(
        new ExampleCommand()
      );
      return $response;
    } 

    /**
     * {@inheritdoc}
     */
    public static function getSubscribedEvents() {
      return [
        FlagEvents::ENTITY_FLAGGED => [['onFlag']]
      ];
    }
  }

It runs the dpm text the next time the page is loaded, but it doesn't seem to be running my custom Ajax response at all, even if I try running a standard Ajax Response from here. Are there some places that you can't run these kind of Ajax Response requests?