Note:

If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

A guide to writing output components and the render methods for them.

Terminology

Don't worry if you don't understand these yet, this document is going to explain them. However for the sake of providing a quick understanding of some of the terminology used in output here it is:

  • Atom A simple building block, think of it like a HTML tag as that is what it is in many cases.
  • Molecule A collection of atoms combined together to serve a single purpose or offer a single interaction.
  • Organism A collection of molecules and atoms combined together to form a part of the user interface, serving one or more related purposes.
  • Element An element is an meta concept for the above, a base from which all atoms, molecules, and organisms begin.
  • Component Used to refer to any or all of the above. A component is a general term for renderable something relating to this output approach.
  • Subcomponent When we speak of subcomponents we are talking about the smaller components that are going to be of a larger component. e.g the molecules that are present in an organism.
  • Renderable Used to mark the object as something that can be converted into output.

Understanding output in Moodle

In 2.8 the direction of output in Moodle was changed, or more accurately re-organised.
Most Moodle sites out there use a third party theme, or have a had a theme created for them. We can assume that themes are the most widely created plugin within Moodle. They deal with the design of the site, and design by nature is a moving, shifting, trending, fluid.
How Moodle produces its look need to be flexible enough to cater to current trends, requirements such as usability and accessibility, be able to keep up with trends, and cater to personal tastes.
We've long had renderers now that allow us to cater to this flexibility, however as Moodle has grown so has its interfaces. There are more interfaces, more controls, more possible interactions.
The move in 2.8 was to bring organisation to what was being done, to bring consistency to the party and the make this flexible a manageable possibility by having an organised set of components to style rather than an endless array of interfaces and unique parts.

The goals for the output project were:

  • Add an element library to Moodle (A page in Moodle listing all of the renderables and how they look in the current theme).
  • Add a complete set of core renderables that should be capable of completely rendering every new user interface.
  • Update the Output API documentation.
  • Create a output guide documentation including best practices.

All of this leans towards making Moodle framework agnostic, so that any frontend framework can be applied to Moodle with as little work as possible.

After reflection and research the decision to use a style of Atomic Design was made. Atomic Design is as you will come to understand later a compartmentalisation approach to interface design that facilitates simplicity and re-use.

Atomic Design, Renderables and Moodle

Renderables have been around for a long time now, they were one of the initial preferred means of creating a reusable output components.
As of Moodle 2.8 there is a new kid on the block, Elements.
Elements within Moodle is based upon the Atomic Design principles outlined by Brad Frost in his Atomic Design blog post and can be one of three distinct types in Moodle, they are either Atoms, Molecules, or Organisms.
These elements are within Moodle actually renderables by inheritance, all elements (atoms, molecules, and organisms) must have an associated render method to produce HTML, but more on that later.

Lets look at the three types of elements within Moodle.

Atoms

Atoms are the smallest part of the puzzle. Easily understood as HTML elements, an image, a table, list etc.
Individually they offer very little, but are essential as they are what all larger things are built out of.

Simply - Atoms don't serve any explicit purpose nor do they provide any interaction, they are just building blocks.

Molecules

Molecules are the combination of atoms into structures that begin to form part of the picture.
Atoms by themselves aren't useful, but by sticking a few of them together we create a molecule.
Think of molecules as simple objects that the user can interact with for a single purpose, a login prompt (title + two inputs + a button), a search form (title + input + button), or a menu (several links).

Simply - Molecules provide a single interaction or purpose. They are constructed of Atoms only.

Organisms

Organisms make things interesting, the are more complex than molecules but not so clearly differentiated.
An organism is a construct of molecules that when combined together form a distinct part of an interface.
They tend to both interesting, and obviously more than a molecule.
The following are examples of molecules:

  • A navigation bar containing a title, some navigation, and a user picture.
  • A user content block (like a forum post) containing a user picture, a title, some content, and a date.
  • A Moodle block containing a header, some actions, content, and a footer.

Simple - Organisms can group several purposes or interactions into one related structure. They are constructed of Molecules.

What about templates and pages?

Atomic Design defines two additional compartmentalisations, templates and pages.

  • Templates it states are the grouping of predominantly organisms into a structure, think of it like a layout. It is organisation without content.
  • Pages are specific instances of the above templates, loaded with content as the user would see them.

In regards to Moodle neither of these two ideas is explicitly dealt with, both ideas however are already partly included in Moodle in the form of theme layouts and current renderers.
Pages are a direct match to this approach, content in Moodle is dynamic and those layouts are where the output and content is joined.
Templates on the other hand are partly covered by layouts (for the page as a whole), and partly covered by renderers.

Renderers form part of that picture because it is within a script that things are assembled.
Again as of Moodle 2.8 with the work on output a best practices guide for renderers has been written which will outline how best to write renderers to match our chosen approach and why they should be written as such.

How we made this fit within the Moodle dodecahedron

Within Moodle we've decided to use the terminology from the Atomic Design approach. As discussed above templates and pages are not explicitly handled within Moodle, however atoms, molecules, and organisms are.
Class auto-loading has being used, and as these things belong to the Output API they have been organised by namespace under classes/output.

The following are the base structures:

core\output\element implements renderable
This is the absolute bottom unit, it can only be utilised by the core Output API. It contains basic functionality to all atoms, molecules and organisms.
core\output\atom extends element
This matches the Atomic Design atom concept. It is a basic building block often equating to just a single HTML tag.
Within Moodle we don't created atom classes for each HTML tag. That approach was considered but the clutter, the classes it would introduce, and the render methods for those classes was deemed to outweigh the advantages having them would provide. Instead in many cases our smallest "renderable" element will be the molecule.
core\output\molecule extends element
This matches the Atomic Design molecule concept. It serves a single purpose/interaction and can consist of atoms (as properties) but because we don't have classes/objects for every atom can also in some situations contain no atom objects at all.
core\output\organism extends element
This matches the Atomic Design organism concept. It is a collection of other molecules and atoms, and can have serve several purposes and/or interactions that have all being grouped under a single umbrella, this organism.

All of these base structure are abstract and cannot be directly instantiated. Instead actual atoms, molecules, and organisms must derive from one of atom, molecule, or organism. The element class is deemed to be internal to the Output API and therefore cannot be extended outside of the core Output API (at least the integrators won't accept it).

The importance of inheritance in rendering

By now you have a good picture of how we've organised output in Moodle in 2.8.
What is left to discuss is the importance of this hierarchy and its impact on how we produce output in renderers.

We know that Atoms form Molecules, which in turn form Organisms.
We try to apply this same inheritance within our renderers so that when you render an organism we start by producing the encompassing structure, then for each of the molecules that make it up we render on each. This passes the molecule to its own render method to produce the molecule. The same goes for the molecules that contain atoms, we produce the structure for the molecule and call render on each atom at the appropriate time for the structure.
Through this means there should in the perfect world scenario be one way to render each organism, molecule, and atom. Thus when a theme designer wishes to change how the search molecule looks for instance they need only change the render method for that one molecule, and every place that molecule is used, either stand alone or as part of a larger organism will be updated at the same time.

Unfortunately, with the present state of Moodle themes this idea of having the minimal possible render methods to produce the most consistent output is but a pipe-dream.
However as time goes on that will slowly correct itself, as more of Moodle is converted and themes begin to develop with this new approach.
For the time being the consistency that having a specific set of components and the organisation of those components is going to be a big win.

The element library

Hopefully you are already familiar with the element library in Moodle; if not then you really should take a look at it and get to understand what is it doing.

The element library is a very important piece in the puzzle that is Output within Moodle.
It shows how a component looks in one or more scenarios, the scenarios usually revolving around varying contents.

Designing and writing a component

A step by step approach to working through the creation and rendering of an element so that it meets the Output standards for Moodle.

Step 1: Are you sure you need to create a component

We want Moodle to contain a limited number of components. The problem that existed before this work was that every bit of code was creating its own output, and we do not want to end up back there.

The very first thing to do is to be absolutely sure that you need to create this component.

Atoms and molecules After the initial release this should be rare. It should be especially rare that you need to write an atom or molecule for a plugin.
Moodle should provide 95% of the atoms and molecules you could ever need. However if you have something that is truly new and unique in some way then perhaps indeed you do need to write a component.

Organisms Writing an organism isn't going to be as rare, certainly not at first anyway. As time progresses obviously we want to settle upon a finite selection of organisms, however it is a reality that we will not be able to cater for all core code and plugins initially. If you find yourself with a unique interface requirement, perhaps for the new and original plugin you are working on then you probably have met the requirement for creating an organism.

In both cases it is important that you search through the components already in Moodle and see if there are any that meet your needs.
If there is something close in Moodle core already then perhaps you need to adjust your design to make use of the existing component rather than introducing something similar but slightly different.
If you find a component you could use in a core plugin then you should create an issue in our Tracker and request that the component be moved from the plugin to core.
Then for the time being copy the component from the plugin you found it in, into your plugin. This way it will look consistent, you can use it and if it does get accepted into core you don't have to change anything about how you use it.

Step 2: Define the component

It very important to be sure of what you want to create.

The first thing to do is to work out what is it going to be, is it an atom, a molecule, or an organism?
Remember the following, they describe each of those in a single sentence:

Atom
A basic building block that severs no purpose or interaction.
Molecule
Serves just a single purpose OR interaction, not usually a part of an interface by itself, grouped with other molecules and atoms to form an organism.
Organism
A part of the interface, it is constructed of molecules and atoms, it can facilitate several like purposes and interactions

It should be possible to create a flow chart to aid this decisions, unfortunately one has not being created yet.

Once you've decided what type of component it is going to be you are ready to start designing what other components (if any) will make it up.

Now is a good time to be very clear about the purpose of your component, as well as any interactions that you want it facilitate. Consider writing down a clear and concise description of your component and sharing what you are planning in the forums, with colleagues or just generally with other developers. This output approach is still fresh and we are all still learning how it works in detail so the more exposure you can get now the easier it will be down the track.

Step 3: Create the component class

Creating a component is really quite simple, the following headings explain what you need to know:

Component location

All components belong to the Output API and should be namespaced within it for autoloading and consistency with Moodle core components. This makes locating components very easy, core components will be located within an output subdirectory of the classes directory as shown below:

lib/classes/output/mycomponent.php

Plugin components will be located in a similar fashion within an output subdirectory of the classes directory. e.g.

mod/myplugin/classes/mycomponent.php

Class name and inheritance

Classes are namespaced for the output API and located in the file above. Because classes are namespaced the actual class name is simply the component name. The same name as was used for the file. They must however extend the appropriate component type, if you are creating a molecule it must extend \core\output\molecule, if its an organism it must extend \core\output\organism. For following is an example of how this would look for a core component:

<?php namespace core\output; defined('MOODLE_INTERNAL') || die();

class mycomponent extends organism {

And for a component you are creating within a module plugin:

<?php namespace mod_myplugin\output; defined('MOODLE_INTERNAL') || die();

class mycomponent extends \core\output\organism {

Class properties

We like to keep components simple to interact with. For that reason we encourage people to store data and subcomponents that will be used during rendering as public class properties. This is done so that data is accessed in a consistent fashion when interacting with a component. For this reason we would rather not see developers adding methods to a component unless truly required.

Subcomponents are a good example. If you were writing a navigation bar organism for example you may have a title molecule, a menu molecule, and a search molecule. The title, menu and search molecules are the components.
These will become public class properties of your component.

Class methods

Components should only have methods to support their own construction. As expressed above all information useful to a renderer should be stored in publicly accessible properties, none of it should have to be accessed via method calls. This is done so that interaction with components is consistent across all components. Methods to aid the construction of the component are encouraged so that information can be easily added to the component.

Construction

The constructor for your component should allow the developer to pass in the required data and subcomponents. Consider when writing the constructor how developers will pass information into the component. In many cases there are going to be two types of data that will commonly be passed in:

  1. Components (or arrays of) that make up parts of your component.
  2. Scalars (or arrays of) e.g. strings, integers, floats and booleans.

Step 4: Write the render methods

Step 5: Write generator samples

Step 6: Style those samples in bootstrapbase and base

Step 7: Use your component

Tracker issues

The following tracker issues relate in one way or another to the development and continued work on Output.

  • MDL-45885 Decide how output components (the issue that saw this document created)
  • MDL-45770 Implement stage 1 tasks from the Render Library specification
  • MDL-41663 Allow renderers and renderables in a namespace to be auto loaded.
  • MDL-45828 Create the element library admin tool.


See also