How can I hide a block on specific content types in Drupal 8? There's the setting for displaying blocks only on specified content types, but not for hiding them. Looks like the PHP filter is out in D8, so not sure how to go about this. I'm sure it's a simple fix.
5 Answers
You can use this module:
Here you can configure a visibility group which hides blocks for a specific content type.
The visibility groups not only provide more options for block visibility, they are also reusable, that means you can apply the same settings on multiple blocks.
Ctools also provides the functionality to hide blocks for content types, but there was an issue, I don't know if this is resolved.
-
Hah, good idea. I needed a solution to make up for settings in another Block Visibility Group, so I don't know why I didn't think to set up a second one with the negated condition. Thanks!– MrweinerCommented Oct 18, 2016 at 17:46
-
The issue was that negating content type condition causes block to be removed from every non-node enity page. And this module perpetuates it, since it uses ctools to accomplish content type validation. More on the topic drupal.org/project/block_visibility_groups/issues/2820631– DominikaCommented Nov 3, 2020 at 13:14
Another way you can do this, just via code (in this example, in your theme's .theme
file), is like so:
/**
* Implements theme_preprocess_block().
*/
function themename_preprocess_block(&$variables) {
// Remove page title block on 'article' content type.
if ($variables['elements']['#id'] == 'themename_page_title') {
$node = \Drupal::routeMatch()->getParameter('node');
if ($node && $node->getType() == 'article') {
$variables['content'] = [];
}
}
}
-
The above code has some issue in
if ($block_id == 'themename_page_title')
because there is no variable define for$block_id
. So the actual code isif($variables['plugin_id'] == 'themename_page_title')
.– ManavCommented Mar 27, 2018 at 9:13
Using geerlingguy's code as is, you'll get a notice about $block_id
variable being undefined.
Place $block_id = $variables['elements']['#id'];
before the if
statement to get rid of the notice.
I tried multiple methods, including the one provided by CTools, Block Visibility Groups and Context. Context works, but it's tedious, since you have to recreate entire blocks layout for specific condition and it crashes when installed with Menu Position. So far the best solution seems to be hook_block_access()
use Drupal\block\Entity\Block;
use Drupal\Core\Session\AccountInterface;
use Drupal\node\NodeInterface;
use Drupal\Core\Access\AccessResult;
/**
* Implements hook_block_access().
*/
function MYMODULE_block_access(Block $block, $operation, AccountInterface $account) {
$node = \Drupal::routeMatch()->getParameter('node');
if ($node instanceof NodeInterface) { //checking if we're on node page
if($node->type->entity->label() == NODE_TYPE && $block->getRegion() == REGION){
if( $operation == 'view' && $block->getOriginalId() == BLOCK_ID){
return AccessResult::forbiddenIf($block
->getRegion() == REGION)
->addCacheableDependency($block);
}
}
}
return AccessResult::neutral();
}
-
1Thanks. Most flexible way, here you can set any needed conditions. Just one thing. For checking NODE_TYPE seems better to use "$node->bundle()" instead of "$node->type->entity->label()". Commented Jul 16, 2022 at 11:38
You can :
- Create a custom plugin condition;
- Place your block in a region;
- And enable your custom condition.
Here is an example of a plugin condition :
<?php
namespace Drupal\my_module\Plugin\Condition;
use Drupal\Core\Condition\ConditionPluginBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides a 'ContentType' condition.
*
* @Condition(
* id = "my_module_node_content_type",
* label = @Translation("Node content type"),
* context_definitions = {
* "node" = @ContextDefinition(
* "entity:node",
* label = @Translation("Node")
* )
* }
* )
*
* @DCG prior to Drupal 8.7 the 'context_definitions' key was called 'context'.
*/
class NodeContentType extends ConditionPluginBase implements ContainerFactoryPluginInterface {
/**
* Creates a new ContentType instance.
*
* @param array $configuration
* The plugin configuration, i.e. an array with configuration values keyed
* by configuration option name. The special key 'context' may be used to
* initialize the defined contexts by setting it to an array of context
* values keyed by context names.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
* The date formatter.
* @param \Drupal\Component\Datetime\TimeInterface $time
* The time service.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition
);
}
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return ['node_type' => NULL] + parent::defaultConfiguration();
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
// Add form checkbox.
$form['node_type'] = [
'#type' => 'checkbox',
'#title' => $this->t('Dot not show on mini site node type'),
'#default_value' => $this->configuration['node_type'],
];
return parent::buildConfigurationForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
$this->configuration['node_type'] = $form_state->getValue('node_type');
parent::submitConfigurationForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function summary() {
return $this->t('Node not type: My node type');
}
/**
* {@inheritdoc}
*/
public function evaluate() {
$node = \Drupal::routeMatch()->getParameter('node');
if ($node && $node->getType() == 'my_node_type') {
return FALSE;
}
return TRUE;
}
}