drupaldrupal-modulesdrupal-viewsdrupal-blocksdrupal-9

Drupal block which filter content type by taxonomy


I am using Drupal 9. I want to give the ability to the admin to place a block and select from the block a taxonomy term in which will filter a content type.

I did the above by creating a custom block with the taxonomy "Sponsor Type" as you can see the screenshot bellow. enter image description here

Also I use views_embed_view to pass the taxonomy as an argument and filter the data using Contextual filters

Drupal embed view

Custom block code:

<?php

namespace Drupal\aek\Plugin\Block;

use Drupal\Core\Block\BlockBase;
use Drupal\Core\Form\FormStateInterface;

/**
 * Provides a 'SponsorsBlock' block.
 *
 * @Block(
 *  id = "sponsors_block",
 *  admin_label = @Translation("Sponsors"),
 * )
 */
class SponsorsBlock extends BlockBase {


  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return [
        "max_items" => 5,
      ] + parent::defaultConfiguration();
  }

  public function blockForm($form, FormStateInterface $form_state) {

    $sponsors = \Drupal::entityTypeManager()
      ->getStorage('taxonomy_term')
      ->loadTree("horigoi");
    $sponsorsOptions = [];
    foreach ($sponsors as $sponsor) {
      $sponsorsOptions[$sponsor->tid] = $sponsor->name;
    }
    $form['sponsor_types'] = [
      '#type'          => 'checkboxes',
      '#title'         => $this->t('Sponsor Type'),
      '#description'   => $this->t('Select from which sponsor type you want to get'),
      '#options'       => $sponsorsOptions,
      '#default_value' => $this->configuration['sponsor_types'],
      '#weight'        => '0',
    ];

    $form['max_items'] = [
      '#type'          => 'number',
      '#title'         => $this->t('Max items to display'),
      '#description'   => $this->t('Max Items'),
      '#default_value' => $this->configuration['max_items'],
      '#weight'        => '0',
    ];


    return $form;
  }


  /**
   * {@inheritdoc}
   */
  public function blockSubmit($form, FormStateInterface $form_state) {
    $this->configuration['sponsor_types'] = $form_state->getValue('sponsor_types');
    $this->configuration['max_items'] = $form_state->getValue('max_items');
  }


  /**
   * {@inheritdoc}
   */
  public function build() {
    $selectedSponsorTypes = $this->configuration['sponsor_types'];
    $cnxFilter = '';
    foreach ($selectedSponsorTypes as $type) {
      if ($type !== 0) {
        $cnxFilter .= $type . ",";
      }
    }

    return views_embed_view('embed_sponsors', 'default', $cnxFilter);
  }

}

My issue now is how to limit the results. If you look above I have added an option "Max items to display" but using the Contextual filters I can't find any way to pass that argument to handle this.


Solution

  • If you use views_embed_view(), you will not be able to access the view object.

    Load your view manually then you can set any properties before executing it:

    use Drupal\views\Views;
    
    
    public function build() {
      $selectedSponsorTypes = $this->configuration['sponsor_types'];
      $cnxFilter = '';
      foreach ($selectedSponsorTypes as $type) {
        if ($type !== 0) {
          $cnxFilter .= $type . ",";
        }
      }
    
      $view = Views::getView('embed_sponsors');
      $display_id = 'default';
      $view->setDisplay($display_id);
      $view->setArguments([$cnxFilter]);
      $view->setItemsPerPage($this->configuration['max_items']);
      $view->execute();
    
      return $view->buildRenderable($display_id);
    }