Theming and Frontend Integration
Theming with Single Directory Components (SDC)
Drupal LMS leverages Drupal's modern Single Directory Components (SDC) for its frontend rendering. This makes theming and customization predictable and powerful. Instead of relying on a large number of theme hooks, the module provides self-contained components that bundle their own Twig, CSS, and JavaScript.
All components are located in the components/ directory.
Key Components
course_card: Renders each course display card on the main/courseslisting page.
course_navigation: The main navigation block that appears on course pages, showing lessons and activities plus a progress indicator bar.
lesson_item&activity_item: The individual rows within the course navigation component.
start_link&course_action_info: Handle the display of the action link on each course (e.g., "Enroll", "Start", "Continue", "Awaits grading").
course_status: A small component for displaying a student's current status (e.g., "In Progress," "Passed", "Failed").
lesson_timer: Displays the countdown timer on timed lessons.
How to Customize Components
To override a component's appearance, you don't need to implement any hooks. Simply copy the component's directory from lms/components/ into your theme's components/ directory. For example, to customize the course card:
- Copy the entire
lms/components/course_card/directory tothemes/custom/your_theme/components/course_card/.
- Clear Drupal's cache.
- You can now safely modify
course_card.twigandcourse_card.csswithin your theme. Drupal will automatically use your version.
Tip: You can see all the properties (variables) available in a component's Twig file by inspecting its *.component.yml file. This is the definitive source for what data you have to work with.
Common Theming Tasks
Add a Custom Field to the Course Card
Let's say you've added a "Difficulty" (field_difficulty) field to your Course group type and want to display it on the course card.
- Implement the hook: In your theme's
.themefile or a custom module, implementhook_views_row_lms_course_card_alter().
- Add the field data to props: This hook allows you to add your field's rendered output to the
extra_fieldsarray that gets passed to the component.
use Drupal\lms\Entity\Bundle\Course;
use Drupal\Core\Cache\CacheableMetadata;
/**
* Implements hook_views_row_lms_course_card_alter().
*/
function mytheme_views_row_lms_course_card_alter(array &$props, Course $course, CacheableMetadata $cacheability) {
if (!$course->get('field_difficulty')->isEmpty()) {
$props['extra_fields'][] = [
'label' => t('Difficulty'),
'content' => $course->get('field_difficulty')->view(['label' => 'hidden']),
];
// Ensure Drupal knows that this component's output depends on the field.
$cacheability->addCacheableDependency($course->get('field_difficulty'));
}
}Note: You must also update your custom course_card.twig file to loop through and print the extra_fields array where you want it to appear.
Add Custom JavaScript to a Component
If you need to add custom JavaScript interactions to an LMS component, you can attach a library from your theme.
- Define a library in your theme's
mytheme.libraries.ymlfile.
- Attach the library in a
hook_preprocess_HOOK()function for the component's Twig template.
// In mytheme.libraries.yml
lms-card-custom:
js:
js/lms-card-custom.js: {}
dependencies:
- core/drupal
- core/jquery
// In mytheme.theme
/**
* Implements hook_preprocess_HOOK() for the course card component.
*/
function mytheme_preprocess_lms_course_card(array &$variables) {
$variables['#attached']['library'][] = 'mytheme/lms-card-custom';
}Block Plugins
The module provides block plugins for navigation and status display:
- StepsBlock (
src/Plugin/Block/StepsBlock.php): Provides the "Course navigation" block that is available only on answer form routes.
- BlockBuilder (
src/BlockBuilder.php): Called by StepsBlock to build the render arrays that are passed to thecourse_navigationcomponent.
Views Integration
Views Custom Handlers
The module integrates with Views through custom handlers in src/Plugin/views/:
- Field Handlers:
LmsEntitySelection: AJAX selection for references
(src/Plugin/views/field/LmsEntitySelection.php)
CourseStatus: Course status display
(src/Plugin/views/field/CourseStatus.php)
CourseTakeLink: Link to start/continue a course
(src/Plugin/views/field/CourseTakeLink.php)
CourseStudentLatestActivity: Last activity timestamp
(src/Plugin/views/field/CourseStudentLatestActivity.php)
- Filter Handlers:
ClassFilter: Filter group content by parent Class. This is in the optional LMS Classes sub-module.
(modules/lms_classes/src/Plugin/views/filter/ClassFilter.php)
- Relationship Handlers:
ClassMemberCourseStatus: Link class members to course status
(src/Plugin/views/relationship/ClassMemberCourseStatus.php)
- Access Handlers:
CoursePermission: Course-specific permission checks
(src/Plugin/views/access/CoursePermission.php)
Included Views
Pre-configured views in the module include:
activities_selection: Activity selection interface
(config/install/views.view.activities_selection.yml)
lessons_selection: Lesson selection interface
(config/install/views.view.lessons_selection.yml)
lms_course_students: Student management
(config/install/views.view.lms_course_students.yml)
lms_courses: Course management
(config/install/views.view.lms_courses.yml)
courses: Public listing of available courses
(config/install/views.view.courses.yml)
| Previous page: Services, Managers, Hooks, and Query Alters |
Next page: Drupal LMS API |
Help improve this page
You can:
- Log in, click Edit, and edit this page
- Log in, click Discuss, update the Page status value, and suggest an improvement
- Log in and create a Documentation issue with your suggestion
Still on Drupal 7? Security support for Drupal 7 ended on 5 January 2025. Please visit our Drupal 7 End of Life resources page to review all of your options.