How to style your Drupal 8 module? - css

We are building a custom Drupal 8 module, but we want control over the admin styling of it. For example style the default links above our table, convert the word -MISSING- to a proper icon, etc.
All can be easily done with CSS and Twig, but the problem is how do you overwrite it? We want to keep using the default seven admin template.
So all CSS and Twig has to be inside the module I guess.
Otherwise a new user that installs our module don't get the new templates.
Update
We think the hook_thme method was the way to go, but still no succes to overwrite the classy/seven block:
function ejb_project_theme() {
$theme['block'] = [
'template' => 'block',
];
$theme['block__ejb_project'] = [
'template' => 'block',
];
$theme['block--ejb_project'] = [
'template' => 'block',
];
$theme['page--block'] = [
'template' => 'block',
];
return $theme;
}

Yes, you need to add the theming to the module through a libraries.yml file on your module folder. Check https://www.drupal.org/developing/api/8/assets for complete information about it.
For templates creation/overriding check Create custom twig templates from custom module and Drupal 8 - Override template with module

The approach you considering is a good one: define your our theme files using hook_theme().
In your .module file:
function ejb_project_theme($existing, $type, $theme, $path) {
return [
'ejb_admin_block' => [
'variables' => [
'attributes' => [],
'var_1' => 'default_output',
],
],
];
}
Then in the module's templates directory you can create a file named: ejb-admin-block.html.twig to provide your markup.
This is basically the inverse of what you describe: instead of overriding Seven's template, you're defining a new one and admin themes have the option to override yours.
For more on the details of the array in hook_theme see the documentation above and the theme system overview article from Drupal.org.

You can check for this also. see screenshot here
place suggested file_name.html.twig in themes/yourtheme/templates dir
there is also a filename from where that output is coming from. you can copy that file and paste into yourtheme/template dir. clear cache. this will work.

You can try:
use \Symfony\Component\HttpFoundation\RedirectResponse;
function hook_page_attachments_alter(array &$attachments) {
$route_match = \Drupal::service('current_route_match');
$route_name = $route_match->getRouteName();
if ($route_name == 'some.route') {
$response = new RedirectResponse("your_path");
$response->send();
}
Either you should redirect to a path or try to call a custom template which will be in your_module/template dir

Related

Drupal 7 hook_theme() not loading template file

I'm trying to get a very simple module to load a template file using drupal's hook_theme(). It's pretty much as simple as you can possibly imagine.
function sectionheader_theme ( $existing, $type, $theme, $path ) {
return array(
'sectionheader' => array(
'variables' => array( 'foo' => NULL ),
'template' => 'sectionheader',
),
);
}
The template is named sectionheader.tpl.php. The rest of the module is working as expected. I've cleared the Drupal cache. I've inserted a die("Debug") statement in this function, and it is being executed, but my template is simply not being called, ever. The template merely has some debug text in it so I can see that it's working, but is not visible in any view of the module.
I've done everything in every example I can find, I've even copied and pasted code directly from other modules, and this template will still not load.
Note, if you have put your template file in a /theme subfolder in your module dir ( which is best practice), you'll also need to specify the file path in hook_theme
function example_theme($existing, $type, $theme, $path) {
return array(
'example_function' => array(
'variables' => array('var1' => array(), 'var2' => array(), 'var3' => array()),
'template' => 'example-template',
'path' => drupal_get_path('module', 'example').'/theme'
),
);
}
I had the same problem as yours, and I solved it by clearing the cache, I searched from the database, and in the cid column of table cache, I get something like "theme_registry:*", and I remove them, it works.
As mentioned in the comment above I hit the same problem. Everything was working fine in a development module but when I simply copied this module into a new one that would become my production module the template file no longer worked. I tried everything mentioned above withut luck. The original module was disabled and only the new one was enabled.
I even went back to see if the original module's theme could work and it didn't. hmmmm.
When I changed the name of the theme it suddenly started to work: the template file was located and displayed.
So, it appears that any module that registers a theme name ---- even if it is disabled --- still registers a theme AND it seems that theme names need to be unique throughout the system.
Answer: look for the same theme name being declared in other modules

Register your theme functions in Drupal

I am new to Drupal and I am working on creating my own theme for our custom module. Can any one please help me understand how to register our theme functions or share any ideas or links that explains the process from scratch.
Register a theme function means implementing hook_theme in your module.
For example, if your module is called "example", then you need to have a function called example_theme in the example.module file. The theme function must return an array or you'll end up with the famous white screen of death.
In example.module:
<?php
// $Id$
// Implements hook_theme
function example_theme(){
return array(
'mydata' => array(
// Optionally, you can make the theme use a template file:
// this line references the file "mydatafile.tpl.php" in the same folder as the module or in the folder of the active theme
'template' => 'mydatafile',
// these variables will appear in the template as $var1 and $var2
'arguments' => array(
'var1' => null,
'var2' => null,
),
),
'myotherdata' => array(
// these variables will appear in the functions as the first and second arguments
'arguments' => array(
'var1' => null,
'var2' => null,
),
)
);
}
// If you don't want to use a template file, use a function called "theme_THEID" to create the HTML.
function theme_myotherdata($var1, $var2){
return "<div>var1= $var1 and var2= $var2</div>";
}
In mydatafile.tpl.php:
<div>mydatafile.tpl.php was called</div>
<ol>
<li>var1: <?php echo $var1; ?></li>
<li>var2: <?php echo $var2; ?></li>
</ol>
You can then later call the theme function manually if needed:
$html = theme('mydata', 'hello world', 123);
$html = theme('myotherdata', 'hello world', 123);
In which case "mydatafile.tpl.php" and "theme_myotherdata" will receive the value "hello world" in $var1 and the value 123 in $var2.
There are many more options, like changing the name of the function, using patterns instead of a fixed name, being able to have the function in another php file or such, check out the link.
Here are a couple more ressources about theming:
The theme guide
Overriding themable output
The Devel module
The Theme developer module (requires the Devel module)
a longuer example that also creates a form/page to use the theme function
By the way, you will need to rebuild the theme registry cache if you add the functions in the .module file after it has been installed, in which case you can do so by clearing the cache (one way is using the button at the bottom of the the Performances page).
NOTE: Slightly different syntax with Drupal 7 (ex. 'arguments' changes to 'variables')
http://www.davidcalculli.com/blog/2012/01/drupal-7-custom-template-only-displaying-the-first-character

Drupal: How to theme a module

I'm trying to theme a modules output.
In particular i'm working on http://drupal.org/project/service_links
Any idea how that works?
Thanks in advance!
Generally, if you want to theme a module you have a few options.
Overwrite theme functions. You can overwrite the theme functions that the module uses/implements to change the markup, one example of such a function is theme_service_links_node_format. You change make a function in your theme's template.php called 'your_theme_name_service_links_node_format' and make your custom markup in it instead.
CSS. If you don't need to change the actual markup of a modules output, you only need to add the needed css, to theme it into your liking.
In some cases, it doesn't look like sercive links is such a case, you can also make your own templates, and make Drupal use them instead.
Another way, again it doesn't look like service is service links is such a case, is to implement preprocess functions in your template.php. This is needed if you want to alter how certain template variables are generated.
If you want to implement your own theming function services links defines 3 themables. In your theme you should imlement the following
yourtheme_service_links_build_link()
yourtheme_service_links_node_format()
yourtheme_service_links_node_format()
'service_links_build_link' => array(
'arguments' => array(
'text' => NULL,
'url' => NULL,
'title' => NULL,
'image' => NULL,
'nodelink' => NULL,
),
),
'service_links_node_format' => array(
'arguments' => array('links' => NULL),
),
'service_links_block_format' => array(
'arguments' => array('items' => NULL),
),
Have a look at http://drupalcode.org/viewvc/drupal/contributions/modules/service_links/service_links.module?view=markup line 389 and below
What's the problem? I mean, every module should use a different name for main container and so. You can use css selector in clever way to refer the template pages.
For example, the FAQ module use identificator to all part of html output, like faq-question and faq-answer in the main page.
Just inspect your resulting code and css it, if possible modify the module-related css!
If the module implements its own theme hooks you can use that. You can also use CSS.

Load view template on module activation

I have developed a blogger-like archive feature (you know, from the feature module).
I want to edit the .module file in order to automatically load the view-template (which is bundled in the feature) into the theme. Is there a way to do it?
On a general level: you should think "features = modules" and leaving theming for... themes! This does not mean that you shouldn't include a template with your feature, but that you should evaluate whether the template you have built suits a general use of your feature or it is specific for your currently used theme. If it is the latter case, you should not package your template file with the feature, but leave it with the theme instead. Just think to how the views module works, to get an idea of what I mean.
[Maybe you are already aware of this and made your considerations to this regards, in which case simply disregard what above. I thought about writing it because your sentence "I want the tpl.php to be actually available for the feature to use it (just as if it were in the active theme folder)" surprised me as general-use templates do not live in the theme folder but in the their module one, and moreover views already provide a "general use" template.]
That said, the way you normally tell drupal to use a given template, is via implementing hook_theme() in your module. In this case - though - given that you are going to override the template defined by views you should implement hook_theme_registry_alter() instead.
Somebody actually already did it. Here's the code snippet from the linked page:
function MYMODULE_theme_registry_alter(&$theme_registry) {
$my_path = drupal_get_path('module', 'MYMODULE');
$hooks = array('node'); // you can do this to any number of template theme hooks
// insert our module
foreach ($hooks as $h) {
_MYMODULE_insert_after_first_element($theme_registry[$h]['theme paths'], $my_path);
}
}
function _MYMODULE_insert_after_first_element(&$a, $element) {
$first_element = array_shift($a);
array_unshift($a, $first_element, $element);
}
Of course you will have to alter the theme registry for your view, rather than for a node (the original example refers to a CCK type).
As on using the template in the views_ui, I am not sure weather the features module already empty the theming cache when you install a feature (in which case you should be good to go). If not, you can trigger it manually by invoking cache_clear_all() from your install file. If emptying the entire cache is too much, you should dig into the views module on how to flush the cache relatively to a single views.
Hope this helps!
Try to add this to your feature .module file
/**
* Implementation of hook_theme_registry_alter().
*/
function MYMODULE_theme_registry_alter(&$theme_registry) {
$theme_registry['theme paths']['views'] = drupal_get_path('module', 'MYMODULE');
}
On the .install file use this
/**
* Implementation of hook_enable().
*/
function MYMODULE_enable() {
drupal_rebuild_theme_registry();
}
Here is my snippet to declare views templates stored in the "template" folder of my "custom_module":
/**
* Implements hook_theme_registry_alter().
*/
function custom_module_theme_registry_alter(&$theme_registry) {
$extension = '.tpl.php';
$module_path = drupal_get_path('module', 'custom_module');
$files = file_scan_directory($module_path . '/templates', '/' . preg_quote($extension) . '$/');
foreach ($files as $file) {
$template = drupal_basename($file->filename, $extension);
$theme = str_replace('-', '_', $template);
list($base_theme, $specific) = explode('__', $theme, 2);
// Don't override base theme.
if (!empty($specific) && isset($theme_registry[$base_theme])) {
$theme_info = array(
'template' => $template,
'path' => drupal_dirname($file->uri),
'variables' => $theme_registry[$base_theme]['variables'],
'base hook' => $base_theme,
// Other available value: theme_engine.
'type' => 'module',
'theme path' => $module_path,
);
$theme_registry[$theme] = $theme_info;
}
}
}
Hope it helps someone.

Drupal theme functions workflow in module

I am a bit newbie in Drupal theming and I can't get one detail in Forum modules theming.
forum.module file contains forum_theme function that controls how this module is themed
and has this line
function forum_theme() {
......
'forum_list' => array(
'template' => 'forum-list',
'arguments' => array('forums' => NULL, 'parents' => NULL, 'tid' => NULL),
),
I also see forum-list.tpl.php file in forum directory, so I start to wonder when this file is called and where it gets data from, but all I can find in forum.module is this function.
function template_preprocess_forum_list(&$variables)
Am I missing something? So in general my question is who and when invokes custom registered theme function, like forum_list
Simple answer is if you in your theme directory put mytheme-forum-list.tpl.php (where mytheme is the name of your theme) and customise it drupal should pick it up (clear the cache first).
This line in template_preprocess_forum calls the Drupal theme function
$variables['forums'] = theme('forum_list',
$variables['forums'],
$variables['parents'],
$variables['tid']);
This will reference the line in forum_theme()
'forum_list' => array(
'template' => 'forum-list',
'arguments' => array('forums' => NULL, 'parents' => NULL, 'tid' => NULL),
),
Which tells the templating enging to look for forum-list.php and provides arguments.
If you install the devel module and turn on the theme developer module. This will show you all of the candidate templates and functions which Drupal will look for when rendering content.
In general (but with specific exceptions) Drupal looks for the best match template and falls back to the pre defined functions.
if there is nothing that matches. Have a look at the theme guide and in specific the section on Overriding themable output you may also find hook_theme of interest.

Resources