Moodle 4.0 developer update
This page highlights the important changes that are coming in Moodle 4.0 for developers. Including how the UX improvements impact custom themes, relevant API changes, and what you can do as developer to prepare for the 4.0 release.
Navigation changes
The core Navigation API has been left mostly untouched. The callbacks to all navigation callbacks remain unchanged and will be called as part of the regular navigation
and settingsnav
initialisation. Some new core classes have been created and exist within a new namespace core/navigation
and serve as conduit to rearrange, cherry-pick existing navigation nodes from the navigation/settingsnav trees and display within the respective navigation type. As such, it is highly recommended to provide unique keys for custom navigation nodes as this helps in the cherry-picking / rearranging process within the new classes.
Primary navigation
The menus have been transitioned to be rendered via templates. Refer to user_menu.mustache
for more information. The lang menu has been moved to reside within the user menu.
The primary navigation (the navbar) apart from the existing content will now display links to the Dashboard, My Courses, Site Admin and Course search, by default. You can still add items to the navbar via the custom menu
option. This will be displayed within the 'More' menu.
Not yet implemented but we are looking at allowing the full addition and removal of any of the primary navigation tabs in the boost theme config file.
Secondary navigation
The main content area shows tabs for secondary navigation with a maximum of 5 items being rendered in this 'more' menu. A new UI component has been created to render menus like this. More information can be found in: /lib/templates/moremenu.mustache
Adding items to the navigation
The secondary navigation pulls information mainly from the settings navigation node from each context. Any plugin that implements the existing navigation hooks will have their items added to the secondary navigation. Existing navigation hooks:
{module}_extend_navigation
{local}_extend_navigation
{report}_report_extend_navigation
{plugin}_extend_navigation_course
{plugin}_extend_navigation_category_settings
Changing the order of tabs
Apart from the previously mentioned functions, you can also create a custom secondary class as mentioned earlier. This will automatically be picked by getter and used to render the secondary nav within the activity. For example, mod_assign/local/views/secondary
.
This is currently only possible on an activity and block level.
Tertiary navigation
Action buttons have been moved to the top of the page and we would encourage you to do the same. If you have any buttons on an activity page that go to another page, or open a form (or similar), then we encourage you to move them from the body of your activity page to the top. All of the core activities have been updated to follow this pattern. Please take a look to see how you can format your activity in a similar fashion. There is no API here. You are welcome to create the buttons and display them as you wish in this top area.
New API functions
Page API
- Magic getters to fetch the primary and secondary navigation and the primary output.
- The
secondarynav
magic getter also checks whether a custom secondary class has been defined within the module's local\views directory. Use this if you want to deviate from the standard secondary nav structure/order. set_secondarynav
- Force override the secondary navigation classset_secondary_navigation
- Sets the_hassecondarynavigation
and optionally the_hastablistsecondarynavigation
to indicate whether a page should render the secondary navigation, and if the secondary navigation should be rendered and behave with a tablist ARIA role (as opposed to its default which is being rendered with a menubar ARIA role).
Navigation library
set_show_in_secondary_navigation
- whether or not a node should be displayed in the secondary nav. Accepts a single boolean argumentset_force_into_more_menu
- whether or not to force a node into the 'More' menu. Accepts a single boolean argument
The activity header class
There is a new activity header class that handles the display of information common to activities. Third party activities are not required to explicitly output this information as part of rendering individual pages.
The common information that are currently handled by the class are:
- title
- description
- completion information
As part of the update it was required that the initial information to be displayed by the class be togglable at a theme and layout level. Taking this into account the following theme level configurable exists:
activityheaderconfig
- An array that currently only enforcesnotitle
but can be expanded in the future.
Boost has this set as true by default options
.
The following layout level options that can be defined:
noactivityheader
- to remove the header in this specific layout.activityheader
- An array that enforces the following options:notitle
nocompletion
nodescription
The class has a page level getter which you can use to fetch the current version of the class. The base state is initialised within the constructor with the completion information only fetched when data is exported for the template.
The class has setters for the following variables which can be leveraged to modify the header for a particular page in the format set_{variable_name}
:
- hidecompletion
- description
- title
Alternately, bulk operations can also be done by passing the above variables in an array to set_attrs
which in turn calls the setters.
Any updates to the activityheader
needs to be performed before the call to $OUTPUT->header
Theme updates
With the changes in boost to incorporate the primary and secondary navigation, third party themes would need to account for the following in their templates:
-
To leverage the activity_header, it's data needs to be exported and included into the base template :
headercontent
being the array element that contains the exported activity_header data
{{#headercontent}}
{{> core/activity_header}}
{{#headercontent}} -
It is recommended to transition towards the secondary/tertiary navigation hierarchy to reduce user cognitive load and with a logical separation of components
- Secondary navigation can be added to the templates by following the example https://github.com/moodle/moodle/blob/master/theme/boost/templates/columns2.mustache#L64-L68 This leverages the secondary navigation class to generate it's content.
-
Flat navigation classes have been marked for deprecation. Themes that leverage the flat_navigation will need to make the following changes in their plugins in order to use it
- Account for the additional changes theme changes
- Indicate that they do not implement secondary navigation via the page's
set_secondary_navigation
function. It is recommended to set this within the root layout file, for example, columns2 - Initialise the flat navigation by introducing the following in the root layout file (if not existent)
$nav = $PAGE->flatnav;
$templatecontext['firstcollectionlabel'] = $nav->get_collectionlabel(); -
In order to reintroduce the settings cog in the templates, you can introduce the following:
<div id="region-main-settings-menu" class="d-print-none {{#hasblocks}}has-blocks{{/hasblocks}}">
<div> {{{ output.region_main_settings_menu }}} </div>
</div>
The jump to maincontent
div is now rendered within the activity header when within an activity context.
Component library
Each Moodle installation now ships with a Moodle User Interface (UI) Component library, a documentation system used to describe all the Bootstrap components and the custom Moodle components. The component Library is a helper tool for developers when creating user interfaces, a testing tool for theme developers and a documentation tool for core developers. The ultimate goal of having a component library is to encourage developers to create consistent user interfaces to improve Moodle's overall user experience.
The library contains pages with documentation about User Interface components. It contains details on how to use the component, what variations are available and the JavaScript events / options are associated with the component.
When writing on these pages it is possible to render core mustache templates using some custom syntax like this:
You can also call core JavaScript or use HTML examples where the HTML code and the rendered result are visible in the Component Library. For more info visit the Moodle templates page or the Moodle JavaScript page.
Each page in the library uses the current CSS from the default theme in your Moodle installation, if you have multiple themes installed and enabled the setting "Allow theme changes on url", the component library will have a theme selector option.
A hosted version of the Component Library can be found at http://componentlibrary.moodle.com.
Enabling the Component Library
Component library pages are written in the markdown language. These pages need to be compiled to HTML pages before the Component Library is visible. To compile the pages the server running Moodle needs to have nodeJS and Grunt tools.
If your server meets all requirements you can enable the library running
$ npm install
$ grunt componentlibrary
Further installation instructions can be found in the Component Library itself.
Documenting new UI Components
There are no set rules for adding new pages in the component library yet. These rules will need to be written and adopted in the integration process for Moodle code.
As a guideline for making this rules consideration are:
- The component library is not about single use components, for example the Moodle grade book (a huge component with many custom features). Or about very common components like buttons, these are already covered by the Bootstrap section of the component library.
- New features should be build keeping in mind the UI part needs to be customisable and if possible (and making sense) reusable. And example would be the new page drawers that we are introducing for the Navigation project. Or the custom primary navigation menus where overflowing items are pushed into a More section.
Theme changes
Edit switch
On theme boost the "Turn editing on" and "Customise this page" buttons have been replaced by an edit switch in the top navbar. Theme Classic will keep using the old buttons. Child themes can choose to use the edit switch if the theme config.php is using this variable
$THEME->haseditswitch = true;
The language menu, which used to be rendered in place of the custom menu has moved to the user dropdown when the user is logged in. If not logged in it will be placed next to the search / notification / messaging icon in the top navbar.
Login page
The login page has been redesigned and allows the admin to configure a background image for the login page only in the theme settings page. This change is available in both Boost and Classic. The login page still has all the features with an improved layout.
The page footer
In large screens, the page footer button is only visible when clicking a help button at the bottom right of the screen.
User initials as profile picture placeholder
If users do not upload a profile picture the user initials are displayed on a rounded gray background as a placeholder picture in the top navbar or any other page using a placeholder image. This change will be available in both Boost and Classic.
With the introduction of this placeholder image the full username will no longer be displayed in the top navbar.
Removal of back to top link
The "back to top" link will be removed for theme boost since the new course index reduced the dependence on page scrolling. Also, the new footer is positioned where this component used to be.
Styling changes
By default rounded edges will be used for UI components, for the page header and main content area the borders will be removed.
New layout page
Theme boost now uses the drawers.php
layout for the course index and blocks.
Question bank changes
There was a big project to deliver Question bank improvements for Moodle 4.0 which added a new plugin type for adding features to the question banks, tracking the version history for each question as it is edited (question table has been split into question
, question_versions
and question_bank_entries
), and tracking where each question is going to be used, with new tables question_references
and question_set_references
. This work was done in Epic MDL-70329 if you want to track down the details of any of the core changes.
Question type plugins
Amazingly, we (Safat and colleagues at Catalyst AU) managed to implement this without breaking most question type plugins, with one important exception if your questions do shuffling like multiple choice does. See MDL-74752. There is a new method called update_attempt_state_date_from_old_version
which you may need to implement.
However, the changes to the question bank, and the other Moodle 4.0 changes, probably broke the Behat tests for your plugin. To help with fixing that, MDL-74130 adds navigation to key question type pages (Preview and Edit for a question, and standard question bank pages like the bank itself, import and export) which should let you fix your test efficiently, and in a way that will work in all Moodle versions since 3.9.
The 'most' in the first paragraph here is because more advance question types may require more effort to fix. For example qtype_combined
which creates multi-part questions like the core qtype_multianswer
; or qtype_pmatch
or qtype_stack
, which store additional data - questions tests - alongside the question itself. How should that work with versioning?) But, if you have not done weird things like that, you are probably safe. If you find anything else that causes problems, please list it here.
The same thing should apply to question behaviour and question import/export format plugins: no significant changes required (probably just fixing the Behat tests because of the navigation changes).
New plugin type: qbank plugins
This is not something that will cause problems for people upgrading from 3.x. Rather, it is an exciting possibility you can explore once you have survived process of upgrading to 4.0. There is a whole new plugin type which you can create to add new features to the question bank. For example extra columns, new actions and bulk actions, and so on. See Question bank plugins.
Activities that use questions
The probable bad news is if you have an activity module which uses questions. So far, the only activity which has been fixed is mod_quiz
in Moodle core, so we don't yet have a good picture of what fixes will be necessary in other activities. Work is about to start fixing mod_studentquiz
, so watching that should give more clues. As we do that, we will try to update this section of this page. Other help writing the information required here would also be greatly appreciated.
The course format system
Most of the logic for rendering and editing a course has been moved to a new subsystem called courseformat. The subsystem is located in "course/format" folder so it includes all the format plugins inside. The methods and modules which are distributed between the course and the course/format folders are now rearranged or refactored to be aligned with the current Moodle coding style.