
Product
Introducing Webhook Events for Pull Request Scans
Add real-time Socket webhook events to your workflows to automatically receive pull request scan results and security alerts in real time.
hmpo-components
Advanced tools
hmpo-components
is a collection of nunjucks components, filters and mixins. These reusable UI elements help ensure consistency and accessibility when developing GOV.UK pages with hmpo-form-wizard.
npm install [--save] hmpo-components;
NOTE:
hmpo-components
v8.0.2 and above uses GOV.UK Frontend v5+, which requires ECMAScript Modules (ESM) and a modern JavaScript bundler.
You must use a JavaScript bundler (such as Rollup, Webpack, or Vite) that supports ESM.
Directly including these modules in <script>
tags in browsers is not supported.
If your project or its dependencies use a mix of CommonJS (CJS) and ESM modules, you will need to configure Rollup with additional plugins to ensure everything is bundled correctly.
npm install govuk-frontend hmpo-components rollup @rollup/plugin-node-resolve @rollup/plugin-commonjs @rollup/plugin-terser
assets/javascripts/app.js
)import { initAll } from 'govuk-frontend';
import 'hmpo-components/all.js';
// ...your custom JS here
initAll();
rollup.config.mjs
)import commonjs from '@rollup/plugin-commonjs';
import { nodeResolve } from '@rollup/plugin-node-resolve';
import terser from '@rollup/plugin-terser';
export default {
input: 'assets/javascripts/app.js',
output: {
file: 'public/javascripts/application.js',
format: 'esm',
sourcemap: true,
},
plugins: [
nodeResolve(),
commonjs(),
terser()
],
};
package.json
"scripts": {
"build:js": "mkdir -p public/javascripts && rollup -c"
}
Build your bundle with:
npm run build:js
<script type="module" src="/public/javascripts/application.js"></script>
If you previously included scripts directly with
<script>
, you will need to update your build pipeline to use ESM and a bundler.
For more options and troubleshooting, see the Rollup documentation and plugin docs.
To use hmpo-components
in your Express app, follow these steps:
hmpo-app
provides a comprehensive setup for applications, streamlining the configurations process. It includes built-in features such as logging, error handling, and session management, making it easier to get started. Additionally, hmpo-app
handles the setup and configuration for hmpo-form-wizard
, which in turn incorporates hmpo-components
to ensure consistency and accessibility in your forms.
const { setup } = require('hmpo-app');
const express = require('express');
const { app, staticRouter, router } = setup({ config: { APP_ROOT: __dirname } });
// Override template file extension from .html to .njk
app.set('view engine', 'njk');
// Mock API to submit data to
staticRouter.use(express.json());
staticRouter.post('/api/submit', (req, res) => {
console.log(`Mock submit API received data: ${JSON.stringify(req.body, null, 2)}`);
setTimeout(() => {
res.json({
reference: Math.round(100000 + Math.random() * 100000)
});
}, 1000);
});
router.use('/eligibility', require('./routes/eligibility'));
router.use('/apply', require('./routes/apply'));
router.get('/', (req, res) => res.redirect('/eligibility'));
app.use(staticRouter);
app.use(router);
app.use(errorRouter);
While hmpo-app
is recommended for its comprehensive setup, you can still use the raw form wizard setup instructions if needed.
const hmpoLogger = require('hmpo-logger');
const express = require('express');
const path = require('path');
const nunjucks = require('nunjucks');
const hmpoComponents = require('hmpo-components');
const i18n = require('hmpo-i18n');
const config = require('./config');
const logger = hmpoLogger.config(config.logs).get();
const app = express();
// log access requests
app.use(hmpoLogger.middleware());
// Add routing for static assets
app.use('/public', express.static(path.resolve(__dirname, 'public')));
app.use('/public/images', express.static(path.resolve(__dirname, 'node_modules', 'hmpo-components', 'assets', 'images')));
// Set up templating engine (Nunjucks)
app.set('view engine', 'html');
const nunjucksEnv = nunjucks.configure([
path.resolve(__dirname, 'views'),
path.resolve(__dirname, 'node_modules', 'hmpo-components', 'components'),
path.resolve(__dirname, 'node_modules', 'govuk-frontend')
], {
express: app,
dev: true, // Set to false in production
noCache: true, // Disable caching in dev
watch: true // Enable template watching in dev
});
// Set up i18n middleware
i18n.middleware(app, {
query: 'lang',
allowedLangs: ['en', 'cy'],
cookie: { name: 'lang' },
watch: true,
baseDir: [
path.resolve(__dirname),
path.resolve(__dirname, 'node_modules', 'hmpo-components')
]
});
// Initialize hmpo-components
hmpoComponents.setup(app, nunjucksEnv);
// Define a simple route to render a template
app.get('/', (req, res) => res.render('pages/index'));
// Start the server
app.listen(config.port, () => {
logger.info('App listening on http://localhost::port', { port: config.port });
});
If rendering as part of an HMPO controller's middleware chain then the field configuration will automatically be set to res.locals.options.fields
by the controller, and will be loaded from here by the components.
For more examples of how to use hmpo-components
, the hmpo-app
example app provides examples of how these components can be integrated within a broader application context.
Additionally, the hmpo-form-wizard
example app demonstrates how hmpo-components
are used within the hmpo-form-wizard
to render form components on each page of a multi-step form flow.
Translation is performed using a req.translate
local function, for example as provided by hmpo-i18n
Components can be called as macros:
{% from "hmpo-input/macro.njk" import hmpoInput %}
{% from "hmpo-submit/macro.njk" import hmpoSubmit %}
{{ hmpoInput(ctx, { id: "fieldId" }) }}
{{ hmpoSubmit(ctx, { key: "textKey" }) }}
hmpoForm(ctx, params, base)
: Renders a form element with configurable attributes and CSRF protection.
hmpoErrorGroup(ctx, params)
: Wraps form fields with GOV.UK styling, adding headings, hints, and error mesages for accessibility and consistency.
hmpoAutoSubmit(ctx, params)
: Creates an auto-submit form wrapper with a loading spinner, help text, and a fallback manual submit button, using GOV.UK styling and configurable delays.
hmpoSubmit(ctx, params, base)
: Generates a submit button with optional text, href link, accessibility attributes, and prevention for double-clicking, ensuring consistent button behaviour in forms.
hmpoCharacterCount(ctx, params, base)
: Renders a character count input field by calling the hmpoTextCount
macro, ensuring users stay within a set character limit.
hmpoCheckboxes(ctx, params, base)
: Generates a checkbox group, handling labels, hints, error messages, and optional conditional fields while ensuring accessibility and validation support.
hmpoDate(ctx, params, base)
: Generates a date input field, handling day, month, and year inputs with validation, error messages, accessibility attributes, and optional inexact date support.
hmpoNumber(ctx, params, base)
: Generates a number input field with numeric input, a pattern attribute for validation, and a width of 10 characters, using the hmpoText
macro.
hmpoPhone(ctx, params, base)
: Generates a phone number input field with a width of 20 characters, tel
input for phone numbers, and a maximum length of 18 characters, using the hmpoText
macro.
hmpoRadios(ctx, params, base)
: Generates a radio button group, handling labels, hints, error messages, inline display options, and conditional reveal content for certain choices.
hmpoSelect(ctx, params, base)
: Generates a dropdown (<select>
) component, handling labels, hints, error messages, accessibility attributes, required validation, and pre-selected values while ensuring consistency with GOV.UK design standards.
hmpoText(ctx, params, base)
: Generates a text input or textarea field, handling labels, prefixes, error messages, accessibility attributes, validation rules, and optional no-past restrictions.
hmpoTextarea(ctx, params, base)
: Creates a textarea input by reusing hmpoText
, setting the input type to textarea
and applying a govuk-!-width-three-quarters
class for styling and consistency.
hmpoWordCount(ctx, params)
: Renders a text input with a word count limit by reusing hmpoTextCount
, setting the type to wordcount
, and applying a govuk-!-width-three-quarters
class for styling.
hmpoField(ctx, params, isPageHeading)
: Dynamically selects and renders the appropriate form component based on the field type, applying GOV.UK styling, handling conditional fields, grouped fields, labels, legends, and error messages.
hmpoTextCount(ctx, params)
: Generates a text area with a character or word count limit, applying validation, error messages, accessibility attributes, and custom messages for under, at, and over-limit states.
Most govuk-frontend parameters can be specified in the fields config, or supplied to the component directly. Label, hint, and legend text is loaded from localisation using a default key structure unless overridden.
label.key
: overridden label key.legend.key
: overridden legend key.hint.key
: overridden hint keyitems
: Array of select box, radio, or checkbox options, or an Array of govuk item objects.legend
: Applicable to radio
button controls, which are wrapped in a HTML fieldset
with a legend
element.For a comprehensive list of all available parameters, refer to the GOV.UK Frontend documentation.
hmpoCircleStep(params)
: Generates a numbered step in a list with a circular icon, optional title, and description, allowing custom classes and attributes for styling and accessibility.
hmpoCircleStepList(params)
: Generates an ordered list of circular step items using hmpoCircleStep
, automatically numbering steps and supporting custom classes, attributes, titles, and descriptions.
hmpoClose(params)
: Generates a close button using the govukButton
component, wrapping it in a <div>
with a data-module="hmpo-close
attribute for Javascript-based functionality.
hmpoCookieBanner(params)
: Generates a cookie banner component with customizable classes, attributes, and a message, ensuring it follows accessibility and SEO best practices with data-nosnippet
.
hmpoDetails(params)
: Renders an expandable details component, allowing for custom content via params.html
or a passed block using caller()
.
hmpoFlashCard(params)
: Generates a flash card component with optional custom classes, attributes, and content, allowing dynamic content insertion via params.content
or a passed block using caller()
.
hmpoFooter(params)
: Renders a customizable GOV.UK-style footer, including navigation links, metadata, licensing information, and copyright details, by incorporating template.njk
.
hmpoInsetText(params)
: Generates an inset text component using govukInsetText, allowing for optional custom content via caller()
or params.html
.
hmpoPrintPage(params)
: Creates a print page link with the text "Print page" (or custom text via params.html
or params.text
), and adds a module for triggering print functionality.
hmpoSidebar(params)
: Generates a sidebar component with optional custom classes and attributes. The sidebar content is inserted within a nested hmpo-sidebar__inner
div, which can also accept additional classes.
hmpoWarningText(params)
: Generates a warning text component by reusing govukWarningText, allowing custom content to be passed through params.html
or caller()
.
hmpoCharsLeft(ctx, params)
hmpoHtml(params)
: Renders content as either individual HTML elements (e.g., paragraphs, headers) or as a list, based on the structure of params
. If the content is a list, it will call hmpoHtmlList
. If the content is individual items, it uses hmpoHtmlItem
. The content can include special formatting, like inset text or headers, based on the content structure.
hmpoHtmlList(params)
: Generates an unordered list (<ul>
) where each list item (<li>
) is rendered by hmpoHtmlItem
. It accepts params.items
as the list content and supports custom classes for the list.
hmpoHtmlItem(tag, value)
: Renders an individual HTML element (paragraph, header, etc.) based on the provided tag and value. This macro also handles special cases, such as rendering inset text or converting Markdown-style headers to HTML tags.
hmpoCharacterCount will be replacing hmpoCharsLeft however for backwards compatability it will still be remaining. When using hmpoCharacterCount you will need specify a maxlength validator for the component in fields.js whereas for hmpoWordCount you will need to specify a maxwords validator. An example can be found below.
'my-character-count': {
...
validate: [
...,
{ type: 'maxlength', arguments: 10 }
]
},
'my-word-count': {
...
validate: [
...,
{ type: 'maxwords', arguments: 10 }
]
},
You may also want to add a translation for the component and that can be found below. You will need to keep %{count} as this is used by the govuk frontend component to parse the character/word count:
Messages in the validation object are required by default
"my-character-count": {
...
(The keys bellow will allow translation of the hint text. %{count} is parsed by gds to show dynamic count)
"textareaDescriptionText": "Enter up to %{count} characters" - shown, instead of dynamic count, to the user if javascript is disabled,
"charactersUnderLimitText": {
"one": "you have one char left" - shown when user has one characters left
"other": "you have %{count} characters left" - shown when user has n characters left
} - shown to user when they have n characters remaining
"charactersAtLimitText": "you have 0 characters remaining" - shown when user has no characters left
"charactersOverLimitText": {
"one": "you have entered 1 character too many " - shown when user has one character over the limit
"other": "you have %{count} characters too many" - shown when user has n. characters over the limit
} - shown to user when they have exceed number of allowed characters
validation: {
...
"maxlength": "You can only enter up to {{maxlength}} characters" - required by default
}
},
"my-word-count": {
...
(The keys bellow will allow translation of the hint text. %{count} is parsed by gds to show dynamic count)
"textareaDescriptionText": "Enter up to %{count} chars" - shown, instead of dynamic count, to the user if javascript is disabled,
"wordsUnderLimitText": {
"one": "you have one word left" - shown when user has one word left
"other": "you have %{count} wrods left" - shown when user has n words left
} - shown to user when they have n words remaining
"wordsAtLimitText": "you have 0 words remaining" - shown when user has no words left
"wordsOverLimitText": {
"one": "you have entered one word too many " - shown when user has one word over the limit
"other": "you have %{count} words too many" - shown when user has n. words over the limit
} - shown to user when they have exceed number of allowed words
validation: {
...
"maxwords": "You can only enter up to {{maxwords}} words" - required by default
}
}
translate
selected
lowercase
uppercase
capscase
hyphenate
date
time
currency
currencyOrFree
url
filter
add
date
filterDates should be provided a a format that moment can decode, such as ISO String format, moment object, or epoch milliseconds.
{{ "2017-06-03T12:34:56.000Z" | date }}
3 June 2017
A moment format can be supplied. The default format is D MMMM YYYY.
{{ "2017-06-3T12:34:56.000Z" | date("DD MMM YYYY HH:MMa") }}
03 Jun 2017 12:34pm
time
filterThe time formatter wraps a formatted time to correct for GDS standard:
{{ "3:00pm" | time }}
3pm
{{ "11 May 2017 at 12:00pm" | time }}
11 May 2017 at midday
{{ "12:00am" | time }}
Midnight
Options can be provided to only do transforms for midday, midnight, or shortened time:
{{ "12:00pm" | time({ short: true, midnight: true, midnight: false }) }}
12pm
Use the controller mixins to extend the base wizard controller:
const BaseController = require('hmpo-form-wizard').Controller;
const DateControllerMixin = require('hmpo-components').mixins.Date;
const DateController = DateControllerMixin(BaseController);
class MyController extends DateController {
}
The DateController
mixin adds day, month, and year fields for a YYYY-MM-DD date field so the hmpoDate
component can be validated and processed properly.
The date field must use the date
validator to use this functionality.
Additional validation errors can be produced and need localisation, for example:
"validation": {
"date": "Enter a complete {{name}}",
"date-year": "Enter a valid year",
"date-month": "Enter a valid month",
"date-day": "Enter a valid day",
"required-day": "Enter a complete {{name}}",
"required-month": "Enter a complete {{name}}",
"required-year": "Enter a complete {{name}}",
"numeric-year": "Enter a year using numbers only",
"numeric-month": "Enter a month using numbers only",
"numeric-day": "Enter a day using numbers only"
}
field
parameter to custom errors to an error to override the link.$hmpo-summary-list: false;
$hmpo-text-size: "big";
FAQs
Component wrappers for wizard fields
The npm package hmpo-components receives a total of 1,946 weekly downloads. As such, hmpo-components popularity was classified as popular.
We found that hmpo-components demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 10 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
Add real-time Socket webhook events to your workflows to automatically receive pull request scan results and security alerts in real time.
Research
The Socket Threat Research Team uncovered malicious NuGet packages typosquatting the popular Nethereum project to steal wallet keys.
Product
A single platform for static analysis, secrets detection, container scanning, and CVE checks—built on trusted open source tools, ready to run out of the box.