Drupal Cheatsheet
Drupal website install and configuration guide.
Lots of parts to building a Drupal site. Installing core, Modules and Themes. This article is documentation for setting up some powerful drupal modules and build an awesome drupal site.
Install Drupal
Here ive listed several ways to install drupal. Drupal can be installed locally or on a remote server.
Install Drupal on Digital Ocean
Digital Ocean has a OpenLiteSpeed
droplet for Drupal which has
- Composer
- Drush
- PHP 8.1
- Configured to serve the
web
directory
Using Drush to Login
Once your drupal litespeed droplet has been installed on Digital Ocean you can use Drush to login. The Great thing about the Digital Ocean litespeed module is it already has drush
installed.
1
vendor/bin/drush uli --uri http://your-site-url
Ensure to add your domain to Digital Ocean before you do the following config. Once you have installed your droplet, open the console from Digital Ocean admin.
- The first question to answer is “what is your domain?”.
- The second question is do you want an ssl
Its harder to configure this stuff later, so best get it right from the start.
Or you can just work from an ip address as the site is accessible from the ip address
Add the droplet and follow the prompts to add
- Your ssh key
- Your domain
- SSL certificate
At this point you should be able to access the Drupal welcome screen via a browser.
The next part relates to if you already have a local drupal install and now you want to deploy it to your remote server.
Install your apps
- Use
scp
to copy yourcomposer.json
file to your server to your project root - Run
composer install
in the root.
Import database
- Activate the
backup and migrate
plugin and export your db from local and import your database to the remote server usingbackup and migrate
module which should be installed on both instances.
Install your theme
- Locally
zip
yourweb/themes/custom
theme folder - Use
scp
to deploy yourcustom.zip
to the server - Use
unzip
to unzip yourcustom.zip
- Clear the cache and reload you, you should be able to see your theme loading.
Deploy files
If you see stylesheet is missing from your drupal site. You just need to deploy the files directory as we do not keep it under version control.
use scp
to deploy web/sites/default/files
best to zip first.
1
zip files.zip -r files
1
scp files.zip your_server:/var/www/html/web/sites/default/
Install Drupal Locally
There are various ways to install Drupal locally. Below are some of the ways I have installed Drupal locally in the past.
Set Up a Drupal Site Locally with DDEV:
- Create a New Drupal Project:
- Open your terminal/command prompt.
- Navigate to the directory where you want to create your Drupal project.
- Run the following commands:
1
2
3
cd your/drupal/project-dir
ddev config --project-type=drupal --docroot=web --create-docroot
ddev composer create "drupal/recommended-project:^10"
Ensure your directory is clean and only has drupal files in it otherwise ddev composer create "drupal/recommended-project:^10"
wont work!
Set PHP version
Edit .ddev/config.yaml
1
2
3
4
5
6
7
8
9
10
11
12
name: my-drupal-project
type: drupal9
docroot: web
php_version: "8.0"
webserver_type: apache-fpm
database:
type: mariadb
version: "10.3"
router_http_port: "8080"
router_https_port: "8443"
additional_flexible_config: false
Start DDev
Ensure your containers in Docker Desktop are running.
1
ddev start
Troubleshooting
If you get error “Could not connect to a Docker provider. Please start or install a Docker provider. For install help go to: https://ddev.readthedocs.io/en/latest/users/install/”
open docker-desktop
and hit the start button then run below command again.
1
ddev config --project-type=drupal10
Fix can’t listen on port 80
Failed to start sitename: unable to listen on required ports, port 443 is already in use,
1
ddev poweroff && docker rm -f $(docker ps -aq)
1
ddev start
- Stop other services using the port. For instance:
1
valet stop
Now start DDev again.
1
ddev start
- Stop all docker containers and Restart docker
1
ddev poweroff && docker rm -f $(docker ps -aq)
Edit Docroot
Fix the error 403 Forbidden
when you visit your ddev site. Update .ddev/config
with a relative path to drupals root index.php.
1
vim .ddev/config.yml
1
docroot: "web"
After updating config file DDev. Ensure you have an index.php
inside the web directory fixing these to issues, This will fix any 403 permission issues.
DDev important note.
Ddev drupal usage changes a little. ie:
To install module using ddev
1
ddev composer require drupal/devel
Install Drush with DDev
1
ddev composer require drush/drush
Install Drupal:
- Access the Drupal site in your browser. The URL will typically be http://
.ddev.site. - Follow the Drupal installation wizard:
- Choose a language.
- Select the installation profile (Standard is typical).
- Enter database connection details (use db for the database host).
- Continue with the installation process.
Configure Site:
- After installation, you’ll be prompted to configure your Drupal site.
- Set up the site name, admin username, password, and other settings.
Stop DDEV:
1
When you're done working on your Drupal site, you can stop the DDEV environment:
1
ddev stop
2. Install Drupal Locally using Valet
Valet comes from the Laravel world. It’s a step up from using mamp/xammp. The difference between valet and mamp is with Valet there is no UI. You run commands on the command line to start and stop valet services such as MySQL and PHP and create local website instances.
** Prerequisites **
- Valet installed locally
- Composer installed
Steps to install Drupal locally
- Create mysql db
- Create site directory, which will become your local url
- Download Latest Stable Drupal zip
- Use valet to serve up your local website
- Go to http://yoursite.test/core/install.php
- Enter database details
3. Install quick start Drupal
** Prerequisites **
- Composer installed
Quick start drupal is good for quick experiments it’s not recommended to use for a production build. but if you’re looking to get a quick local off the ground just to try out a plug-in or test a vanilla install it’s good for that.
Install Quick-Start Drupal locally with Composer
Running the below command will create a drupal play ground.
- Start a local site on http://127.0.0.1:8888/
- Install the latest version of drupal
- Using sqlite db
- Install the demo_uami food magazine theme
- The admin login details will be output in the commandline for you
1
2
composer create-project drupal/recommended-project drupal
cd drupal && php -d memory_limit=256M web/core/scripts/drupal quick-start demo_umami
Restart the quick-start site
After you close it (Ctrl-C) and you want to start it again
1
php -d memory_limit=256M web/core/scripts/drupal quick-start
More information
drupal download drupal install
Drupal Settings.php file
Set the config sync directory. This will allow drush updatedb
to sync your site configuration to the database. Note: for a composer installed drupal site you will have 2 settings.php files. The settings.php file you want to update is located in the web directory. You can rename the other settings.php to be settings_backup.php
1
$settings['config_sync_directory'] = '../config/sync';
Essential Drupal Modules and themes for Site Building
When creating pretty basic stock standard website. This is modules I must have and This is what I use these modules for.
Pathauto module
Automatically change the urls to be prettier https://www.drupal.org/project/pathauto
1
composer require 'drupal/pathauto:^1.13'
Linkit Module
Break up links into 2 parts. The URL and the label.
https://www.drupal.org/project/linkit
Dev version for drupal 11
1
composer require 'drupal/linkit:^6.1'
Media Library (core module)
Use existing images in media library Ensure fields are set to media rather then image.
MicroContent module
For creating global blocks
Works with drupal 11 https://www.drupal.org/project/microcontent
1
composer require 'drupal/microcontent:^2.0'
Entity Reference Display Module
Configure the display of Referenced entities
Not yet ready for D11
1
composer require 'drupal/entity_reference_display:^2.0'
Paragraphs
For creating flexible / movable / resusable global blocks. Pair it with Microcontent.
1
composer require 'drupal/paragraphs:^1.18'
https://www.drupal.org/project/paragraphs/
Block field
Reference blocks created with views from the paragraphs modules
There is only a development version of this module which is not ready for Drupal 11
reference a block from a paragraph field
Development for D11 underway
1
composer require 'drupal/block_field:^1.0@RC'
https://www.drupal.org/project/block_field
Backup and Migrate Module
Not ready for Drupal 11
1
composer require 'drupal/backup_migrate:^5.0'
Better Exposed Filters Module
The Better Exposed Filters module replaces the Views’ default single- or multi-select boxes with radio buttons or checkboxes, respectively. Description fields and Select All/None links can be added to exposed filters to make for a better user experience.
Dev version for Drupal 11
1
composer require 'drupal/better_exposed_filters:^7.0@beta'
https://www.drupal.org/project/better_exposed_filters
Metatag Module
- Set certain content types to no index
- Set individual pages to no index
- Add seo meta tags to content
https://www.drupal.org/project/metatag
Works with Drupal 11
1
composer require 'drupal/metatag:^2.0'
Current Page Breadcrumbs Module
Breadcrumbs are native to drupal, however we need the current page Breadcrumb to display
No D11 version
1
composer require 'drupal/current_page_crumb:^1.5'
For a more advanced module that is compadible with D11.
Easy breadcrumb Module
1
composer require 'drupal/easy_breadcrumb:^2.0'
Mega Menu Module
Not compadible with D11
1
https://www.drupal.org/project/simple_megamenu
Antibot Module
Prevent forms from being submitted without JavaScript enabled
No version for drupal 11
1
composer require 'drupal/antibot:^2.0'
reCAPTCHA v3 Module
antispam
Webforms and Webforms UI Modules
forms
Bootstrap5 Themes
1
composer require 'drupal/bootstrap5:^4.0'
Drush
With a new drupal install either locally or on a remote server drush is probably one of the first modules you will want to install. It will help you do lots of other things that would otherwise be too complex to accomplish without Drush.
Get version of Drupal and PHP you are running.
1
drush status
Update sync database
The updatedb
command is used to update the locate database on Unix-like systems. This database is used by the locate command to quickly find files on the filesystem.
What Does updatedb Do?
- Scans the Filesystem: It scans directories in the filesystem to create an index of file names and their locations.
- Updates the Database: The collected information is stored in a database file, usually located at /var/lib/mlocate/mlocate.db or a similar path.
- Optimizes Search Performance: By maintaining an indexed list of files, it allows the locate command to retrieve results much faster than using find.
When Should You Run updatedb?
You should run drush updatedb
:
- After Adding or Deleting Many Files: If you’ve recently made significant changes to your filesystem (e.g., installed new software, moved directories, or deleted files), you may want to update the database to reflect these changes.
- If locate Results Are Outdated: If the locate command isn’t finding files that exist or is showing files that have been deleted, running updatedb will refresh the index.
1
drush updatedb
List installed modules
1
drush pm:list --status=enabled
Remove flag to get all installed modules, regardless of status
Enable Module
1
ddev drush en paragraphs
List Themes
1
drush pm-list --type=theme
Enable Theme
1
ddev drush theme-enable bootstrap5
Set theme as default
1
2
ddev drush cset system.theme default bootstrap5 --yes
ddev drush cr
Generate a one time login link
1
cd /your/drupal/site/
1
drush uli --uri example.com
Trouble Shooting
The Drush launcher could not find a local Drush in your Drupal site.
1
vendor/bin/drush uli --uri http://your-site-url
Find Drush version
1
drush --version
Update Drush
You might need to add the ^
to the beginning of the version number ie ^12.0.2
in the composer.json
file.
1
composer update drush/drush
Uninstall Drupal Module
1
drush pm:uninstall module_name
Remove the Module:
1
composer remove drupal/module_name
** same command but with ddev **
Uninstall the Module:
1
ddev drush pm:uninstall module_name
Remove the Module:
1
ddev composer remove drupal/module_name
Drupal Views
Customizing Views
Customizing views is Best done from the view admin rather then the twig files. the view admin gives you all the options to add classes and html.
Outputting a block view
if you have generated a block with your view ensure to output it in one of the following ways
- block layout
- as a paragraph block
Create a Hero Banner
see sample screenshot - https://share.cleanshot.com/0rSd0qQ2
- block type for banner
- content type for homepage
- view to get the fields from homepage
- display mode to only display the required fields
Create a Related posts view
https://youtu.be/sTRiJR7MiXQ?si=i6CRY6aBlNVWNJfH
- create view
- go to contextual filters
- search for tax - select has taxonomy term id When the filter value is not available
- provide a default value - Taxonomy term ID from URL.
Create a view block with fields
Create the view of content type Select the format to display fields Add specific fields to the fields section (fields need to be created for your content type) Add css class for container Set title to be none
Display content just from the current node
- Add a contextual filter
- Add content then ID
- Click provide default value
- Content id from url
- Hit apply
as you are using the view to output content the content will also appear on the page from the fields itself on the content type. set them to disabled to hide them
Views basics
views are like a custom query in wp. you can create a page out of a view or a block
Examples
- blog feed
Fields
you can choose what fields are added to the view
- fields can be reordered
Formats
- table
- grid
- unformatted list
- html list
Filter
- filter criteria of the view by taxonomy
- filters can be exposed to users on the frontend
Duplicating a view
- go to structure, content, duplicate view
Drupals block based page builder
It was awesome to discover that you could work with the same “block based page builder” in Drupal” using the wonderful Paragraphs module in way same way as the Wordpress ACF block based page builder.
** Prerequisites **
- An operational Drupal site
- The paragraphs module installed
Create paragraph types
- Go to structure
- Go to paragraph types
Add a paragraph type
You can create a paragraph type for:
- Grid
- Cards
- Gallery
- Text with image
- Whatever
Add fields to your paragraph type
- Text
- Image
Remove labels
- Go to /admin/structure/paragraphs_type
- go to manage display
- set labels to hidden
Attach paragraphs to the content type
- Go to structure
- Content types
- Locate the basic page content type or another content type of your preference
- Manage fields (hit the main btn label on basic page)
- Add field
- Select paragraph under reference revisions
- Give it a name like “page blocks” or “cpt blocks”
- Type of item to reference is “paragraph”
- Set to unlimited
- Choose to include or exclude your paragraph blocks
Back on a basic page
- the blocks you added should be there
Config paragraph display settings
- Go to structure
- Go to content types
- Go to basic page - manage form display
- Scroll down to paragraphs / blocks
- Hit the cog wheel to open the settings
creating custom paragraph blocks
Custom Paragraph Blocks Drupal
If you’re already read some of my other articles related to the Drupal way of creating a modern flexible content page builder with paragraphs module [[2023-01-18-Drupals-block-based-page-builder]] then you may now want to take it a step further with this article about paragraph blocks
Setup the paragraphs directory
1
2
3
cd your_theme_folder
mkdir templates/paragraphs
cd templates/paragraphs
Use twig debug to check for filename overide suggestions
1
touch paragraphs--twig-debug-suggestion.html.twig
Copy the existing module template into your custom theme
1
cp modules/contrib/paragraphs/templates/paragraph.html.twig your_theme_folder/templates/paragraphs/paragraphs--twig-debug-suggestion.html.twig
Paragraph template initial code
code from modules/contrib/paragraphs/templates/paragraph.html.twig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{%
set classes = [
'paragraph',
'paragraph--id--' ~ paragraph.id(),
'paragraph--type--' ~ paragraph.bundle|clean_class,
view_mode ? 'paragraph--view-mode--' ~ view_mode|clean_class,
not paragraph.isPublished() ? 'paragraph--unpublished',
]
%}
{% block paragraph %}
<div{{ attributes.addClass(classes) }}>
{% block content %}
{{ content }}
{% endblock %}
</div>
{% endblock paragraph %}
Overide with your custom code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{%
set classes = [
'paragraph',
'paragraph--type--' ~ paragraph.bundle|clean_class,
view_mode ? 'paragraph--view-mode--' ~ view_mode|clean_class,
not paragraph.isPublished() ? 'paragraph--unpublished',
'my-webform-paragraph-module'
]
%}
{% block paragraph %}
<div{{ attributes.addClass(classes) }}>
{% block content %}
<div class="container">
<div class="row">
<div class="col-lg-8 bg-primary">
<div class="box">
{{content.field_form_title}}
{{ content.field_form_intro_text }}
</div>
</div>
<div class="col">
<div class="box">
{{content.field_webform}}
</div>
</div>
</div>
</div>
{% endblock %}
</div>
{% endblock paragraph %}
Managing Images in Drupal
Drupal shines when it comes to managing images. Specifically around serving an appropriate size images to the user regardless of what size the image was originally loaded into the site.
Enable media embed modules
- swap out the default media icon module for the drupal embed media icon module
When you add images to the Text (formatted, long, with summary). you want to have a choice of image sizes for it to display at.
What image size do we need
- wide
- square
- full landscape
- portrait
- enable the built in media modules
- create styles
/admin/config/media/image-styles
- create view modes
/admin/structure/display-modes/view
- go to
/admin/structure/media/manage/image/display/
and set your custom view mode to use your new image style
edit ckeditor
- edit your ckeditor mode
/admin/config/content/formats/
- choose basic html or whatever editor you enabled
- scroll down to
CKEditor 5 plugin settings
and choose media - enable
user can overide default view settings
- scroll down to
embed media
- enable the custom image sizes under ` View modes selectable in the ‘Edit media’ dialog `
Setting custom image sizes
Best to implement image sizes at the start of the project
Its built into the core
- create your ideal image size
- In the
Manage Display
apply the custom image size by hitting thecog wheel
to your image field on your paragraph block
/admin/config/media/image-styles
** Add in your style **
crop
in which can set a custom size
Build Drupal Pages with Content Reference Entities
A content entity based page construction technique. This technique is native to Drupal and is suitable for working with premade finished nodes of content. So you can create content once and then reference it from unlimited nodes. This is the central powerful feature of this type of website build.
Its a 3 step process
- Create the content type with all the required fields
- Create the content based on the content type
- Reference/pull in this content from other content types such as basic page or a parent block of some sort.
What are the benefits?
- Global blocks (1 central source of content for a node, that can be reused in different content entities)
- Translatable
- Close to core implementation
- Flexible content ordering via drag and drop
How to build blocks with content entities
Blocks are content types
- Create a content type for a block.
- Add a field to the block that is of type content (which is under reference)
- Go to manage fields
- Go to entity reference (under field type)
- Go to edit
- Under reference types add all the content types the field is able to refernce
Attach to a page
- Add the content reference field to a basic page content type
- Go to content types
- Go to manage fields
Example
The most basic use-case for this technique is allowing blocks to be added to a basic page
- Add a content reference field to the basic page content type
- Allow the field to reference other content types
Blocks can reference other blocks
Create a slider block that can slide cards and or articles
- Create a content type called slider
- Create a content type called card
- In the slider content type add a content reference field
Allow the reference field to access the Card and Artical content types
Block display
By default the block you reference display as links to the content. This is not useful. What we need is the full content to display.
** Display the full block content **
- Go to structure / content types
- Select your block content type
- Go to manage fields
- Add field of
display mode
- Create a display mode
- Hit save on the following screen
** Set the display option **
On the following edit field screen, under excluded display modes
- Choose full
- Choose include selected display modes
- Save settings
Set the entity reference field display mode
Go back to manage fields (use the breadcrumbs at the top of the screen)
- Under manage display
- Locate the entity reference field
- Under the format column choose
selected display mode
- Hit save
Now back on the frontend, rather then the block displaying a link to edit its content it will display the full content
Global Blocks with Drupal Paragraphs and Block Modules
To archive flexible page layouts made up of global block content.
Prerequisites
- Install paragraphs module
- Install block field module
- Paragraphs module configured and added to a basic page content type
Key parts
- Create a block. it can be of a custom block type
- Create a paragraph type admin/structure/paragraphs_type
- Add a field and choose block(plugin)
- Set the default value to your block on the edit field settings page.
- Add your global block to the page using paragraph module
Create a page builder
Create a page builder for your drupal pages by utilising nested paragraph blocks
Custom display modes
Drupal offers some ways to change the appearance of your content forms in the admin and also the appearance of your content on the frontend view. This article is focused on archiving different Display modes for the frontend view by showing how to create and apply a display mode
Create a display mode for the content type.
Create a custom dipslay mode for the content type ` /admin/structure/display-modes/view `
Enable the display mode for the content type.
- Go to manage display
- in the custom display settings
- enable your custom display mode
Configure the fields
Enable or disable, all your fields so that your display mode reflects the content you want returned.
Configure your paragraph to use the display mode
- On your custom paragraph Type.
- In the mangage display,
- The format needs to be set to rendered entity
- Assign your new custom display mode. which is hidden under the cog wheel
Preprocess Functions
Preprocess functions are used to modify variables before they are used in the template. This allows developers to customize the output of a page without having to modify the template itself. Preprocess functions are used to add, remove, or alter variables that are used in the template.
Preprocess functions are typically used when you need to modify the variables that are used in the template. For example, if you need to add a custom variable to the template, you can use a preprocess function to do so.
Where to add these functions
themename.theme
Overview
- preprocess functions are optional - if they can be used they will be if not they will be skipped
- preprocess functions are Specific to a template (hook) based on naming convention
- preprocess functions always has 1 param
When to use preprocess functions
- Use a preprocess function to alter/remove or add variables
- Make small alterations to the html output
- Any logic that is more complex then a simple if / else file consider refactoring into a preprocess function to keep template files nice and clean.
Naming Convention
function THEME_preprocess_H00K()
- HOOK is the name of the template your preprocessing variables for
The easiest way to determine what hook
to use is to enable twig debug mode
Example
1
2
3
4
5
function THEMENAME_preprocess_node(&$variables) {
$variables['simple_string'] = array(
'#markup' => 'a simple_string'
);
}
1
2
3
<div class = "string">
{{simple_string}}
</div>
** Example - Add suffix to post author lable if logged in **
1
2
3
4
5
function THEMENAME_preprocess_node(&$variables) {
if($variables['logged_in'] == TRUE && $variables['node']->getOwnerId() == $variables['user']->id()) {
$variables['label']['#suffix'] = '-you are the author';
}
}
** Example - Add new variable to template **
Use twig dump function to see the new variable added to the template
1
2
3
4
5
6
7
8
function THEMENAME_preprocess_node(&$variables) {
$variables['current_user_is_owner'] = FALSE;
if($variables['logged_in'] == TRUE && $variables['node']->getOwnerId() == $variables['user']->id()) {
$variables['label']['#suffix'] = '-you are the author';
$variables['current_user_is_owner'] = TRUE;
}
}
Function Naming Conventions
function THEME_preprocess_HOOK()
1
2
**example**
function bartik_preprocess_page()
** More specific targeting example **
1
2
3
THEMENAME_preprocess_node__42(): This is the most specific version and will only be called for a node with an ID of 42.
THEMENAME_preprocess_node__article(): This would be called for any article node, but not for other node types.
THEMENAME_preprocess_node(): This will be called for all nodes.
- The hook refers to the base name of the template file
- Use Twig Debug to find the hook name for the template file
You can ommit the hook part and add hook as param instead, for adding a variable to every template file - warning this will be called alot
Inject var into every template
1
2
function THEMENAME_preprocess(&$variables, $hook)
Dynamically add layout class to a field
Based on a boolean value which is set in the paragraph block.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
function THEME_preprocess_paragraph(&$variables) {
// Get the paragraph type.
$paragraph_type = $variables['paragraph']->bundle();
if ($paragraph_type === 'cards') {
// Add a class to the paragraph's attributes.
$variables['attributes']['class'][] = 'container cards__wrapper';
//dynamically add layout class to cards to set the layout
// Access the boolean field value.
$boolean_value = $variables['paragraph']->get('field_brand')->value;
// Add a variable for use in the Twig template.
$variables['is_active'] = (bool) $boolean_value;
// Optionally, add logic based on the value.
if ($boolean_value) {
if (isset($variables['content']['field_card_micro_content'])) {
// Add a custom CSS class to the field wrapper.
$variables['content']['field_card_micro_content']['#attributes']['class'][] = 'row-cols-2';
}
} else {
if (isset($variables['content']['field_card_micro_content'])) {
// Add a custom CSS class to the field wrapper.
$variables['content']['field_card_micro_content']['#attributes']['class'][] = 'row-cols-4';
}
}
}
}
Extensive example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
function AERO_preprocess_field(&$variables) {
/**
* title 1 for edge advantage
*/
if ($variables['element']['#field_name'] == 'field_aero_edge_title_1') {
// Pass a flag or tag type to the template.
$variables['custom_tag'] = 'h3';
$variables['attributes']['class'][] = 'edge-advantage__title';
}
/**
* title 2 for edge advantage
*/
if ($variables['element']['#field_name'] == 'field_aero_edge_title_2') {
// Pass a flag or tag type to the template.
$variables['custom_tag'] = 'h3';
$variables['attributes']['class'][] = 'edge-advantage__title';
}
/**
* title 3 for edge advantage
*/
if ($variables['element']['#field_name'] == 'field_aero_edge_title_3') {
// Pass a flag or tag type to the template.
$variables['custom_tag'] = 'h3';
$variables['attributes']['class'][] = 'edge-advantage__title';
}
// Add a custom CSS class to edge_text field
if ($variables['element']['#field_name'] == 'field_aero_edge_text_1') {
$variables['attributes']['class'][] = 'edge-advantage__text';
}
if ($variables['element']['#field_name'] == 'field_aero_edge_text_2') {
$variables['attributes']['class'][] = 'edge-advantage__text';
}
if ($variables['element']['#field_name'] == 'field_aero_edge_text_3') {
$variables['attributes']['class'][] = 'edge-advantage__text';
}
}
//More efficient way to add classes to fields
function AERO_preprocess_field(&$variables) {
// Define a mapping of field names to CSS classes.
$field_class_map = [
'field_stat_number_1' => 'stats__number',
'field_stat_number_2' => 'stats__number',
];
// Check if the current field is in the map and apply the corresponding class.
$field_name = $variables['element']['#field_name'];
if (isset($field_class_map[$field_name])) {
$variables['attributes']['class'][] = $field_class_map[$field_name];
}
}
//Target paragraphs on a page
function THEMENAME_preprocess_paragraph(&$variables) {
/**
* Implements hook_preprocess_paragraph().
*/
// Get the paragraph type.
$paragraph_type = $variables['paragraph']->bundle();
// Add a CSS class based on paragraph type.
if ($paragraph_type === 'stats') {
// Add a class to the paragraph's attributes.
$variables['attributes']['class'][] = 'container stats__wrapper';
}
// Add a class based on specific conditions.
if ($paragraph_type === 'image_block' && $variables['paragraph']->id() == 123) {
$variables['attributes']['class'][] = 'special-image-block-class';
}
}
More info
Microcontent
Microcontent is a drupal module for usable fragments of content that can be configured to display throughout your site.
- Microcontent is a module
- Microcontent is the blueprint for reusable content
- Reference peices of microcontent from paragraphs module
- When working with microcontent and paragraphs - create the microcontent first and then the paragraph block to reference it.
** Tips **
- sometimes its best to set the paragraphs to locate the microcontent via checkboxes rather then autocomplete as the user may not know what options are available
** Trouble Shooting **
Paragraphs not finding the microcontent?
- ensure the label is not disabled or hidden in the field display settings. by default the reference field locats content via the label
Display
- Configure the display of microcontent in the admin by disabling fields in the manage display
Frontend
By default the microcontent you reference display as links to the content. This is not useful. What we need is the full content to display.
install entity reference display module
Display the full block content
- Go to structure / content types
- Select your paragraph type
- Go to manage fields
- Add field of
display mode
- Create a display mode
- Hit save on the following screen
Set the display option
On the following edit field screen, under excluded display modes
- Choose full
- Choose include selected display modes
- Save settings
Set the entity reference field display mode
Go back to manage fields (use the breadcrumbs at the top of the screen)
- Under
manage display
- Locate the
entity reference field
- Under the format column choose
selected display mode
- Hit save
Now back on the frontend, rather then the block displaying a link to edit its content it will display the full content
Radix
Radix is a Drupal theme that evan has its own cli. Pretty cool. Radix promotes the use of self contained components. By using the radix cli
, you can create your own components to override the radix components. I made this list of radix templates I find myself overriding all the time so having this list makes it easier and faster for me to override the default radix templates. I dont use the cli that much as that is meant for self contained components which i dont use.
1
drupal-radix-cli add block
Then you can override the block using the block component in your radix theme.
1
2
3
4
5
6
7
8
9
10
{#
/**
* @file
* Template for a block.
*/
#}
{% include 'radix:block' with {
label: false,
} %}
Whatever option you choose from the for coming list, all the necessary files will be copied into your themes component folder to create an overriding component. That being said, you can still override these templates in the manual way
by getting the theme template suggested name of the template and override the radix template with the relative code samples below.
** Prerequisites **
twig debug installed
Heading
1
2
3
4
5
6
7
8
9
{% if title %}
{%
include 'radix:heading' with {
heading_html_tag: 'h3',
content: title
}
%}
{% endif %}
Refers to:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
{#
/**
* @file
* Heading component.
*
* Bootstrap Documentation
* https://getbootstrap.com/docs/5.3/content/typography/#headings
*
* Full List Utility Classes
* https://github.com/twbs/bootstrap/blob/v5.3.0/dist/css/bootstrap.css#L214
*
* Available properties:
* - heading_html_tag : The HTML tag to use for the header.
* Defaults to h1 (h1|h2|h3|h4|h5|h6)
* - display: When you need a heading to stand out, consider using a display heading—a larger,
* slightly more opinionated heading style.
* - content: Content text for the heading.
* - heading_attributes: Attributes array.
* - heading_utility_classes: This property contains an array of utility classes.
* - heading_link_utility_classes: This property contains an array of utility classes.
* - title_link: Optional link for the heading. If provided, it wraps the heading.
*/
#}
{% apply spaceless %}
{% set heading_html_tag = heading_html_tag|default('h2') %}
{% set display = [display] ?? [] %}
{% set heading_attributes = heading_attributes ?: create_attribute() %}
{% set heading_classes = display|merge(heading_utility_classes ?: []) %}
{% if title_link %}
{% set heading_link_attributes = create_attribute().setAttribute('href', title_link) %}
{% set heading_link_classes = heading_link_utility_classes ?: [] %}
{% endif %}
{% if content %}
<{{heading_html_tag}} {{ heading_attributes.addClass(heading_classes) }}>
{% block heading_content %}
{% if title_link %}
<a {{ heading_link_attributes.addClass(heading_link_classes) }}>
{{ content }}
</a>
{% else %}
{{ content }}
{% endif %}
{% endblock %}
</{{heading_html_tag}}>
{% endif %}
{% endapply %}
Field
In twig debug you should see
BEGIN OUTPUT from 'themes/custom/theme_name/templates/field/field.html.twig'
and in this file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{% include 'radix:field' with {
label_hidden: false,
multiple: true,
label: 'Field Label',
items: [
{ content: '<p>Item one content</p>' },
{ content: '<p>Item two content</p>' },
{ content: '<p>Item three content</p>' }
],
entity_type: 'node',
field_name: 'field_example',
field_type: 'text_long',
label_display: 'above',
attributes: create_attribute(),
title_attributes: create_attribute()
} %}
The code from field.twig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
{#
/**
* @file
* Template for a field component.
*
* To override output, copy the "field.html.twig" from the templates directory
* to your theme's directory and customize it, just like customizing other
* Drupal templates such as page.html.twig or node.html.twig.
*
* Instead of overriding the theming for all fields, you can also just override
* theming for a subset of fields using
* @link themeable Theme hook suggestions. @endlink For example,
* here are some theme hook suggestions that can be used for a field_foo field
* on an article node type:
* - field--node--field-foo--article.html.twig
* - field--node--field-foo.html.twig
* - field--node--article.html.twig
* - field--field-foo.html.twig
* - field--text-with-summary.html.twig
* - field.html.twig
*
* Available variables:
* - attributes: HTML attributes for the containing element.
* - label_hidden: Whether to show the field label or not.
* - title_attributes: HTML attributes for the title.
* - label: The label for the field.
* - multiple: TRUE if a field can contain multiple items.
* - items: List of all the field items. Each item contains:
* - attributes: List of HTML attributes for each item.
* - content: The field item's content.
* - entity_type: The entity type to which the field belongs.
* - field_name: The name of the field.
* - field_type: The type of the field.
* - label_display: The display settings for the label.
* - field_utility_classes: Additional classes to be added to the field wrapper.
* - field_title_utility_classes: Additional classes to be added to the field title wrapper.
*
*
* @see template_preprocess_field()
*/
#}
{%
set classes = [
'field',
'field--name-' ~ field_name|clean_class,
'field--type-' ~ field_type|clean_class,
'field--label-' ~ label_display,
]
%}
{%
set title_classes = [
'field__label',
label_display == 'visually_hidden' ? 'visually-hidden',
]
%}
{% if label_hidden %}
{% if multiple %}
<div{{ attributes.addClass(classes, 'field__items') }}>
{% for item in items %}
<div{{ item.attributes.addClass('field__item') }}>{{ item.content }}</div>
{% endfor %}
</div>
{% else %}
{% for item in items %}
<div{{ attributes.addClass(classes, 'field__item') }}>{{ item.content }}</div>
{% endfor %}
{% endif %}
{% else %}
<div{{ attributes.addClass(classes) }}>
<div{{ title_attributes.addClass(title_classes) }}>{{ label }}</div>
{% if multiple %}
<div class='field__items'>
{% endif %}
{% for item in items %}
<div{{ item.attributes.addClass('field__item') }}>{{ item.content }}</div>
{% endfor %}
{% if multiple %}
</div>
{% endif %}
</div>
{% endif %}
Copy the above code into your custom file using one of the suggestions provided by twig debug
breadcrumb
1
2
3
4
5
6
{%
include 'radix:breadcrumb' with {
breadcrumb: breadcrumb,
}
%}
refers to
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
{#
/**
* @file
* Template for a Breadcrumb component.
*
* Available config:
* - breadcrumb_utility_classes: An array of utility classes.
*/
#}
{% apply spaceless %}
{%
set breadcrumb_classes = [
'breadcrumb',
]|merge(breadcrumb_utility_classes ?: [])
%}
{% set breadcrumb_attributes = attributes ?: create_attribute() %}
{% block breadcrumb %}
{% if breadcrumb %}
<nav aria-label="breadcrumb">
<ol {{ breadcrumb_attributes.addClass(breadcrumb_classes) }}>
{% for item in breadcrumb %}
<li class="breadcrumb-item {{ not item.url ? 'active' }}">
{% if item.url %}
<a href="{{ item.url }}">{{ item.text }}</a>
{% else %}
{{ item.text }}
{% endif %}
</li>
{% endfor %}
</ol>
</nav>
{% endif %}
{% endblock %}
{% endapply %}
Block
1
2
3
4
5
6
7
8
9
10
{#
/**
* @file
* Template for a block.
*/
#}
{% include 'radix:block' with {
html_tag: 'div',
} %}
Referring to file in radix/src/components/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
{#
/**
* @file
* Template for a Block component.
*
* Available config:
* - html_tag: The HTML tag for the block.
* - utility_classes: An array of utility classes.
*/
#}
{% set classes = [
'block',
bundle ? 'block--' ~ bundle|clean_class,
id ? 'block--' ~ id|replace({"_": "-"})|clean_class,
]|merge(utility_classes ? utility_classes : []) %}
{% if html_tag %}
<{{ html_tag }}{{ attributes|without('id').addClass(classes) }}>
{% endif %}
{{ title_prefix }}
{% if label %}
{% block label %}
<h2{{ title_attributes }}>{{ label }}</h2>
{% endblock %}
{% endif %}
{{ title_suffix }}
{% block content %}
{{ content }}
{% endblock %}
{% if html_tag %}
</{{ html_tag }}>
{% endif %}
Views
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
{#
/**
* @file
* Theme override for main view template.
*
* Available variables:
* - attributes: Remaining HTML attributes for the element.
* - css_name: A css-safe version of the view name.
* - css_class: The user-specified classes names, if any.
* - header: The optional header.
* - footer: The optional footer.
* - rows: The results of the view query, if any.
* - empty: The content to display if there are no rows.
* - pager: The optional pager next/prev links to display.
* - exposed: Exposed widget form/info to display.
* - feed_icons: Optional feed icons to display.
* - more: An optional link to the next page of results.
* - title: Title of the view, only used when displaying in the admin preview.
* - title_prefix: Additional output populated by modules, intended to be
* displayed in front of the view title.
* - title_suffix: Additional output populated by modules, intended to be
* displayed after the view title.
* - attachment_before: An optional attachment view to be displayed before the
* view content.
* - attachment_after: An optional attachment view to be displayed after the
* view content.
* - dom_id: Unique id for every view being printed to give unique class for
* Javascript.
*
* @see template_preprocess_views_view()
*/
#}
{% apply spaceless %}
{% set views_attributes = attributes ?: create_attribute() %}
{% set views_title_attributes = views_title_attributes ?: create_attribute() %}
{% set views_header_attributes = views_header_attributes ?: create_attribute() %}
{% set views_filters_attributes = views_filters_attributes ?: create_attribute() %}
{% set views_rows_attributes = views_rows_attributes ?: create_attribute() %}
{% set views_empty_attributes = views_empty_attributes ?: create_attribute() %}
{% set views_footer_attributes = views_footer_attributes ?: create_attribute() %}
{% set views_attachment_before_attributes = views_attachment_before_attributes ?: create_attribute() %}
{% set views_attachment_after_attributes = views_attachment_after_attributes ?: create_attribute() %}
{% set views_pager_attributes = views_pager_attributes ?: create_attribute() %}
{% set views_more_attributes = views_more_attributes ?: create_attribute() %}
{% set views_feed_icons_attributes = views_feed_icons_attributes ?: create_attribute() %}
{%
set views_classes = [
'view',
'view-' ~ id|clean_class,
'view-id-' ~ id,
'view-display-id-' ~ display_id,
dom_id ? 'js-view-dom-id-' ~ dom_id,
css_name ? 'view-' ~ css_name,
]|merge(view_view_utility_classes ?: [])
%}
{%
set views_title_classes = [
'view-title',
]|merge(views_title_utility_classes ?: [])
%}
{%
set views_header_classes = [
'view-header',
]|merge(views_header_utility_classes ?: [])
%}
{%
set views_filters_classes = [
'view-filters',
]|merge(views_filters_utility_classes ?: [])
%}
{%
set views_rows_classes = [
'view-content',
]|merge(views_rows_utility_classes ?: [])
%}
{%
set views_empty_classes = [
'view-empty',
]|merge(views_empty_utility_classes ?: [])
%}
{%
set views_footer_classes = [
'view-footer',
]|merge(views_footer_utility_classes ?: [])
%}
{%
set views_attachment_before_classes = [
'attachment',
'attachment-before',
]|merge(views_attachment_before_utility_classes ?: [])
%}
{%
set views_attachment_after_classes = [
'attachment',
'attachment-after',
]|merge(views_attachment_after_utility_classes ?: [])
%}
{%
set views_pager_classes = [
'pager',
]|merge(views_pager_utility_classes ?: [])
%}
{%
set views_more_classes = ['']|merge(views_more_utility_classes ?: [])
%}
{%
set views_feed_icons_classes = [
'feed-icons',
]|merge(views_feed_icons_utility_classes ?: [])
%}
<div {{ views_attributes.addClass(views_classes) }}>
{% block views_view_wrapper %}
{{ title_prefix }}
{% block views_view_title %}
{% if title %}
<div {{ views_title_attributes.addClass(views_title_classes) }}>
{{ title }}
</div>
{% endif %}
{% endblock %}
{{ title_suffix }}
{% block views_header %}
{% if header %}
<div {{ views_header_attributes.addClass(views_header_classes) }}>
{{ header }}
</div>
{% endif %}
{% endblock %}
{% block views_filters %}
{% if exposed %}
<div {{ views_filters_attributes.addClass(views_filters_classes) }}>
{{ exposed }}
</div>
{% endif %}
{% endblock %}
{% block views_attachment_before %}
{% if attachment_before %}
<div {{ views_attachment_before_attributes.addClass(views_attachment_before_classes) }}>
{{ attachment_before }}
</div>
{% endif %}
{% endblock %}
{% block views_rows %}
{% if rows %}
<div {{ views_rows_attributes.addClass(views_rows_classes) }}>
{{ rows }}
</div>
{% elseif empty %}
<div {{ views_empty_attributes.addClass(views_empty_classes) }}>
{{ empty }}
</div>
{% endif %}
{% endblock %}
{% block views_pager %}
{% if pager %}
<div {{ views_pager_attributes.addClass(views_pager_classes) }}>
{{ pager }}
</div>
{% endif %}
{% endblock %}
{% block views_attachment_after %}
{% if attachment_after %}
<div {{ views_attachment_after_attributes.addClass(views_attachment_after_classes) }}>
{{ attachment_after }}
</div>
{% endif %}
{% endblock %}
{% block views_more %}
{% if more %}
{{ more|add_class(views_more_classes) }}
{% endif %}
{% endblock %}
{% block views_footer %}
{% if footer %}
<div {{ views_footer_attributes.addClass(views_footer_classes) }}>
{{ footer }}
</div>
{% endif %}
{% endblock %}
{% block views_feed_icons %}
{% if feed_icons %}
<div {{ views_feed_icons_attributes.addClass(views_feed_icons_classes) }}>
{{ feed_icons }}
</div>
{% endif %}
{% endblock %}
{% endblock %}
</div>
{% endapply %}
Radix views view component
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{% include 'radix:views-view' with {
title: 'View Title',
header: view_header,
footer: view_footer,
rows: view_rows,
empty: 'No data available',
pager: view_pager,
exposed: exposed_filters,
feed_icons: feed_icons,
more: more_link,
attachment_before: attachment_before_content,
attachment_after: attachment_after_content,
css_name: 'banner',
dom_id: 'unique-dom-id',
view_view_utility_classes: ['bg-primary, p-5, d-flex, align-items-center']
} %}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
{#
/**
* @file
* Theme override for main view template.
*
* Available variables:
* - attributes: Remaining HTML attributes for the element.
* - css_name: A css-safe version of the view name.
* - css_class: The user-specified classes names, if any.
* - header: The optional header.
* - footer: The optional footer.
* - rows: The results of the view query, if any.
* - empty: The content to display if there are no rows.
* - pager: The optional pager next/prev links to display.
* - exposed: Exposed widget form/info to display.
* - feed_icons: Optional feed icons to display.
* - more: An optional link to the next page of results.
* - title: Title of the view, only used when displaying in the admin preview.
* - title_prefix: Additional output populated by modules, intended to be
* displayed in front of the view title.
* - title_suffix: Additional output populated by modules, intended to be
* displayed after the view title.
* - attachment_before: An optional attachment view to be displayed before the
* view content.
* - attachment_after: An optional attachment view to be displayed after the
* view content.
* - dom_id: Unique id for every view being printed to give unique class for
* Javascript.
*
* @see template_preprocess_views_view()
*/
#}
{% apply spaceless %}
{% set views_attributes = attributes ?: create_attribute() %}
{% set views_title_attributes = views_title_attributes ?: create_attribute() %}
{% set views_header_attributes = views_header_attributes ?: create_attribute() %}
{% set views_filters_attributes = views_filters_attributes ?: create_attribute() %}
{% set views_rows_attributes = views_rows_attributes ?: create_attribute() %}
{% set views_empty_attributes = views_empty_attributes ?: create_attribute() %}
{% set views_footer_attributes = views_footer_attributes ?: create_attribute() %}
{% set views_attachment_before_attributes = views_attachment_before_attributes ?: create_attribute() %}
{% set views_attachment_after_attributes = views_attachment_after_attributes ?: create_attribute() %}
{% set views_pager_attributes = views_pager_attributes ?: create_attribute() %}
{% set views_more_attributes = views_more_attributes ?: create_attribute() %}
{% set views_feed_icons_attributes = views_feed_icons_attributes ?: create_attribute() %}
{%
set views_classes = [
'view',
'view-' ~ id|clean_class,
'view-id-' ~ id,
'view-display-id-' ~ display_id,
dom_id ? 'js-view-dom-id-' ~ dom_id,
css_name ? 'view-' ~ css_name,
]|merge(view_view_utility_classes ?: [])
%}
{%
set views_title_classes = [
'view-title',
]|merge(views_title_utility_classes ?: [])
%}
{%
set views_header_classes = [
'view-header',
]|merge(views_header_utility_classes ?: [])
%}
{%
set views_filters_classes = [
'view-filters',
]|merge(views_filters_utility_classes ?: [])
%}
{%
set views_rows_classes = [
'view-content',
]|merge(views_rows_utility_classes ?: [])
%}
{%
set views_empty_classes = [
'view-empty',
]|merge(views_empty_utility_classes ?: [])
%}
{%
set views_footer_classes = [
'view-footer',
]|merge(views_footer_utility_classes ?: [])
%}
{%
set views_attachment_before_classes = [
'attachment',
'attachment-before',
]|merge(views_attachment_before_utility_classes ?: [])
%}
{%
set views_attachment_after_classes = [
'attachment',
'attachment-after',
]|merge(views_attachment_after_utility_classes ?: [])
%}
{%
set views_pager_classes = [
'pager',
]|merge(views_pager_utility_classes ?: [])
%}
{%
set views_more_classes = ['']|merge(views_more_utility_classes ?: [])
%}
{%
set views_feed_icons_classes = [
'feed-icons',
]|merge(views_feed_icons_utility_classes ?: [])
%}
<div {{ views_attributes.addClass(views_classes) }}>
{% block views_view_wrapper %}
{{ title_prefix }}
{% block views_view_title %}
{% if title %}
<div {{ views_title_attributes.addClass(views_title_classes) }}>
{{ title }}
</div>
{% endif %}
{% endblock %}
{{ title_suffix }}
{% block views_header %}
{% if header %}
<div {{ views_header_attributes.addClass(views_header_classes) }}>
{{ header }}
</div>
{% endif %}
{% endblock %}
{% block views_filters %}
{% if exposed %}
<div {{ views_filters_attributes.addClass(views_filters_classes) }}>
{{ exposed }}
</div>
{% endif %}
{% endblock %}
{% block views_attachment_before %}
{% if attachment_before %}
<div {{ views_attachment_before_attributes.addClass(views_attachment_before_classes) }}>
{{ attachment_before }}
</div>
{% endif %}
{% endblock %}
{% block views_rows %}
{% if rows %}
<div {{ views_rows_attributes.addClass(views_rows_classes) }}>
{{ rows }}
</div>
{% elseif empty %}
<div {{ views_empty_attributes.addClass(views_empty_classes) }}>
{{ empty }}
</div>
{% endif %}
{% endblock %}
{% block views_pager %}
{% if pager %}
<div {{ views_pager_attributes.addClass(views_pager_classes) }}>
{{ pager }}
</div>
{% endif %}
{% endblock %}
{% block views_attachment_after %}
{% if attachment_after %}
<div {{ views_attachment_after_attributes.addClass(views_attachment_after_classes) }}>
{{ attachment_after }}
</div>
{% endif %}
{% endblock %}
{% block views_more %}
{% if more %}
{{ more|add_class(views_more_classes) }}
{% endif %}
{% endblock %}
{% block views_footer %}
{% if footer %}
<div {{ views_footer_attributes.addClass(views_footer_classes) }}>
{{ footer }}
</div>
{% endif %}
{% endblock %}
{% block views_feed_icons %}
{% if feed_icons %}
<div {{ views_feed_icons_attributes.addClass(views_feed_icons_classes) }}>
{{ feed_icons }}
</div>
{% endif %}
{% endblock %}
{% endblock %}
</div>
{% endapply %}
unformatted views
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{%
include 'radix:views-view--unformatted' with {
title: 'View Title',
rows: view_rows,
row_utility_classes: [
'col-12',
'col-md-6',
'col-lg-4',
],
default_row_class: true,
rows: rows|map(row => row|merge({
attributes: row.attributes.setAttribute('data-row-color', 'purple')
})),
}
%}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
{#
/**
* @file
* Implements a template to display a view of unformatted rows.
*
* Available variables:
* - title: The title of this group of rows. Can be empty.
* - rows: An array of the view's row items. Each row contains:
* - attributes: The HTML attributes for the row.
* - content: The actual content of the row.
* - view: The view object.
* - default_row_class: A boolean indicating whether default row classes should be used.
* - row_utility_classes: An array of optional utility classes to be used.
*
* @see template_preprocess_views_view_unformatted()
*/
#}
{% apply spaceless %}
{% block views_unformatted_title %}
{% if title %}
{%
include 'radix:heading' with {
heading_html_tag: 'h3',
content: title
}
%}
{% endif %}
{% endblock %}
{% block views_unformatted_rows %}
{% for row in rows %}
{%
set row_classes = [
default_row_class ? 'views-row',
]|merge(row_utility_classes ?: [])
%}
<div{{row.attributes.addClass(row_classes)}}>
{{ rows }}
</div>
{% endfor %}
{% endblock %}
{% endapply %}
Override node
In twig debug BEGIN OUTPUT from 'themes/custom/radix_blocks/templates/content/node.html.twig'
In node.html.twig
1
{% extends "@radix/content/node.twig" %}
The code from this file which is located in themes/radix/src/components/content/node.twig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
{#
/**
* @file
* Template for a Node.
*/
#}
{%
set classes = [
'node',
node.isPromoted() ? 'node--promoted',
node.isSticky() ? 'node--sticky',
not node.isPublished() ? 'node--unpublished',
node.bundle|clean_class,
node.bundle|clean_class ~ '--' ~ view_mode|clean_class,
]
%}
<article{{ attributes.addClass(classes) }}>
{{ title_prefix }}
{{ title_suffix }}
{% block content %}
{% if not page %}
<h2{{ title_attributes }}>
<a href="{{ url }}" rel="bookmark">{{ label }}</a>
</h2>
{% endif %}
{% if display_submitted %}
<footer>
{{ author_picture }}
<div{{ author_attributes }}>
{% trans %}Submitted by {{ author_name }} on {{ date }}{% endtrans %}
{{ metadata }}
</div>
</footer>
{% endif %}
<div{{ content_attributes }}>
{{ content }}
</div>
{% endblock %}
</article>
Overide a paragraphs module
Overide node title
BEGIN OUTPUT from 'core/modules/node/templates/field--node--title.html.twig'
Code from field–node–title.html.twig file
1
2
3
4
5
6
7
8
9
{% if not is_inline %}
{% include "field.html.twig" %}
{% else %}
<span{{ attributes }}>
{%- for item in items -%}
{{ item.content }}
{%- endfor -%}
</span>
{% endif %}
navbar
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
{#
/**
* @file
* Template for Navbar component.
*
* Available config:
* - navbar_container_type: false | sm | md | lg | xl | xxl | fluid
* - placement: default | fixed-top | fixed-bottom | sticky-top
* - navbar_expand: sm | md | lg | xl | false
* - navbar_theme: dark | light (default: light)
* - navbar_utility_classes: An array of utility classes.
*
* Available blocks:
* - branding
* - left
* - right
*/
#}
{% apply spaceless %}
{% set nav_attributes = nav_attributes ?: create_attribute() %}
{% set navbar_container_attributes = navbar_container_attributes ?: create_attribute() %}
{% set placement = placement ?? '' %}
{% set navbar_expand = navbar_expand ?? 'lg' %}
{% set navbar_theme = navbar_theme ?? null %}
{%
set navbar_container_classes = [
navbar_container_type is null ? 'container' : '',
navbar_container_type ? 'container' ~ (navbar_container_type ? '-' ~ navbar_container_type : '') : '',
]|merge(navbar_container_utility_classes ?: [])
%}
{%
set nav_classes = [
'navbar',
navbar_expand ? 'navbar-expand-' ~ navbar_expand : '',
placement,
]|merge(navbar_utility_classes ?: [])
%}
{% if navbar_theme %}
{% set nav_attributes = nav_attributes.setAttribute('data-bs-theme', navbar_theme) %}
{% endif %}
<nav {{ nav_attributes.addClass(nav_classes) }}>
<div {{ navbar_container_attributes.addClass(navbar_container_classes) }}>
{% block branding %}
{{ branding }}
{% endblock %}
{% block navbar_toggler %}
<button class="navbar-toggler collapsed" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbar-collapse" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
{% endblock %}
<div class="collapse navbar-collapse">
{% block left %}
{{ left }}
{% endblock %}
{% block right %}
{{ right }}
{% endblock %}
</div>
</div>
</nav>
{% endapply %}