I wanted to add for block it custom type class in twig layout file: block.html.twig
But i have no idea how to get type.
Class is just needed for styling needs, cause i have many blocks in multiple languages. I don't want to style elements by their custom ids.
Actually i found one working solution, which one uses Theme hook:
/**
* Implements hook_preprocess_HOOK() for block.html.twig.
*/
function MYTHEME_preprocess_block(&$variables) {
// adding custom attribute class for block
if ($variables['elements']['#base_plugin_id'] == 'block_content') {
$blockType = strtr($variables['content']['#block_content']->bundle(), '_', '-');
$variables['attributes']['class'][] = 'block--type-' . $blockType;
}
}
This one is adding class for custom block types only. But works for my needs.
Related
In Drupal 9, I can create a new field called file in some content type, e.g. in Article.
Then for this new field in Manage Display I can select Format Settings: File Table.
Finally, I can add a new page (Article type) and attach some files.
After saving, I have a page with a table.
My question: how do I add a class to this table? I know I can add styles in css stylesheets, but maybe there is a way to add a class directly to the table in a node?
I mean node not View. It just so happens that for View I already know how to do it. But I don't know how to do this for Node
Thank you
ok
The hooks are there for that. If you want to update the node renderable array, you can use the preprocess hook :
/**
* Implements hook_preprocess_HOOK().
*/
function my_theme_preprocess_node(&$variables) {
/** #var \Drupal\node\Entity\Node $node */
$node = $variables['node'];
if ($node->bundle() == 'article'
&& $variables['view_mode'] == 'full') {
// $variables['content']['files']['#attributes']['class'][] = 'your-class';
}
}
In your case, you want to update the field, it might be cleaner to edit the field directly :
/**
* Implements hook_preprocess_field().
*/
function your_theme_preprocess_field(&$variables, $hook) {
$element = $variables['element'];
}
I have a content type as "news". for this content type i need to show latest 5 articles. so i created block by using views. it is showing articles finely but i need to add my own css using twig files. i tried following options but none of them worked correctly.
block--newsblock.html.twig
block--newsblock-block.html.twig
views--view-newsblock-block.html.twig
But when i applied in following way , the field template is calling.
views-view-fields--newsblock--block.html.twig
What i want is for first element in block i need to show some teaser text for rest of them i need to show only title. how can i do it?
activate twig debug and look at your console
it will tell you suggestions of file names to use
Alternatively add this hook to your_theme_name.theme to proppose your own suggestion
/**
* Implements hook_theme_suggestions_HOOK_alter() for block templates.
*/
function your_theme_theme_suggestions_block_alter(array &$suggestions, array $variables) {
$block_id = $variables['elements']['#id'];
/* Uncomment the line below to see variables you can use to target a block */
// print $block_id . '<br/>';
/* Add classes based on the block id. */
switch ($block_id) {
case 'your_block_id':
$suggestions[] = 'block__newsblock';
break;
}
}
it will be then block--newsblock.html.twig
I could add extra functionality to a dataobject if I extend it with a dataextension. For example I've got an Item which gets extended from a module with stock keeping functionality. Let's say the Item also gets's extended form a few other modules.
After the extension with the stock keeping functionality, I'd like to display the availability of the item in the frontend, for example with a green/red dot. How can I get this dot's markup inside my template for the detail page(ItemPage.ss) and the include (Item.ss) for the overview page of items without overwriting the whole template. Just adding this one part, like the way I extend a function on my base class?
That could be a way to add extra markup to the original template.
Inside dataobject or global dataobject extension
public function ExtraTemplateHTML($position) {
$html = null;
foreach($this->owner->extend('updateExtraTemplateHTML') as $positionBlocks) {
if(isset($positionBlocks[$position])) {
foreach($positionBlocks[$position] as $htmlBlock) {
$html .= $htmlBlock->getValue();
}
}
}
return $html;
}
Inside the specific dataobject extension
public function updateExtraTemplateHTML($htmlBlocks) {
$viewer = new SSViewer(__CLASS__);
$html = $viewer->process($this->owner);
$htmlBlocks['bottom'][] = $html;
$topHtml = HTMLText::create();
$topHtml->setValue(123);
$htmlBlocks['top'][] = $topHtml;
return $htmlBlocks;
}
Original Template
$ExtraTemplateHTML(top)
...
...
$ExtraTemplateHTML(bottom)
Extension Template
Than just write a new template for your extension with the content you would like to add.
You cannot partially change a template, you can only substitute the template with another. So, keeping this in mind you should keep modular architecture with many logical includes.
Another possible way to extend existing content is using DOM and javascript. But you should think about side effects. For example if you add extra textual content then it won't be visible by crawlers and will effect your SEO. But for decorative enhancements, like adding extra coloured dot, this approach will work.
Building a site in Drupal 8, using classy subtheme. Run into a puzzling theming issue - adding body class to html.html.twig based on a taxonomy term on that node.
Themers use this to customize page display, in my case using it to define a few sections of my site so I can change color and format.
I have tried some preprocess functions I saw on google but to no result.
Has anyone else run into and solved this issue?
Use this to get all fields of the node and check for whatever you need:
\Drupal::service('current_route_match')->getParameter('node')->toArray();
In your .theme file you can use the html preprocess hook:
function your_theme_preprocess_html(&$variables) {
$body_classes = [];
$nodeFields = \Drupal::service('current_route_match')->getParameter('node')->toArray();
// if something, then set $body_classes to something.
$variables['attributes']['class'] += $body_classes;
}
And then in your html twig template add the attributes to the body element:
<body{{ attributes }}>
Hope this helps.
With the answer of Frank Drebin I get a PHP fatal error (Unsupported operand types) with the "+=" operand. If you want to add the node ID and node type to your body class, you can use this code for example:
// Add the node ID and node type to the body class
$body_classes = [];
$nodeFields = \Drupal::service('current_route_match')->getParameter('node')->toArray();
if (is_array($nodeFields) && count($nodeFields) > 0) {
if (isset($nodeFields['nid'])) {
$body_classes[] = 'node-' . $nodeFields['nid'][0]['value'];
}
if (isset($nodeFields['type'])) {
$body_classes[] = $nodeFields['type'][0]['target_id'];
}
}
$variables['attributes']['class'] = $body_classes;
How can I modify or pre-process the <body> tag to add the class body? I don't want to create a whole html.tpl.php just to add a class.
In your theme's template.php file use the preprocess_html hook:
function mytheme_preprocess_html(&$vars) {
$vars['classes_array'][] = 'new-class';
}
Remember to clear the caches once you've implemented the hook or Drupal won't pick it up.
The documentation for the html.tpl.php template documents the $classes variables as String of classes that can be used to style contextually through CSS.. If you look at the code for the template, this variable is used in the class attributes of the produced body element:
<body class="<?php print $classes; ?>" <?php print $attributes;?>>
The $classes variables is actually already set by template_process() for any template file and build from the content of the $classes_array variable.
So to add a class to the body of your page, you should add this class to the $classes_array value from your theme (or module)'s implementation of hook_preprocess_html():
function THEME_preprocess_html(&$variables) {
$variables['classes_array'][] = 'new-class';
}
Since this is the core defined template and process function, any well-behaving theme should re-use the same variables.
I had to use different array keys in the same hook to make it work:
function THEME_preprocess_html(&$vars) {
$vars['attributes_array']['class'][] = 'foo2';
}
The Context module allows you to add a class to the body tag as well.
This can be useful if you need the class to be added under certain conditions.
You find this options under the reaction "Theme HTML" :
The answer appears to depend on context. Here's what I've found via trial-and-error:
If your hook_preprocess_html() is in a module, use $vars['classes_array'][].
If it's in a theme, use $vars['attributes_array']['class'][].
Common Body Class module provide users to add classes to any page through the an interface.
The interface has options to select multiple user roles as well as pages where the class can be rendered.
I applied this technique on a site that someone else built. It didn't work at first but then dug deeper and found that the $classes variable was not being output in the tpl file. So if it's not working, check that.
For Drupal 7 install http://drupal.org/project/body_class. It will help you to add seperate classes for each node in body tag
You can check "https://www.drupal.org/project/page_specific_class" to add class to body tag of any page
It's a simple way to add a class based on the URL, Drupal 9.
No need to enable the Modules.
/**
* Implements hook_preprocess_html().
*/
function THEME_NAME_preprocess_html(&$variables) {
// Get the current path
$current_path = \Drupal::service('path.current')->getPath();
$internal_path = \Drupal::service('path_alias.manager')->getAliasByPath($current_path);
// Assign it to body class
$variables['attributes']['class'][] = str_replace("/", "", $internal_path);
}
Refer: http://www.thirstysix.com/how-can-i-add-body-class-based-path-page-specific-class-drupal-9