
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
hof-controllers
Advanced tools
This module is now deprecated and has been superceded by the following modules:
The form, base and start controllers have been removed and functionality has been moved back into hof-form-wizard.
Please see the hof guide for more information.
A collection of controllers extended from passports-form-wizard Wizard, Form Controller:
require('hmpo-form-wizard').Controller
var controllers = require('hof-controllers');
Accessed as base from hof-controllers
var baseController = require('hof-controllers').base;
Extends from passports-form-wizard Wizard, Form Controller.
{
clearSession: true,
/* step options */
}
In the wizard options
hofWizard(steps, fields, {
/* wizard options */
params: '/:action?'
});
In the view template
a href='page_name/edit'
Or override in step options
{
continueOnEdit: true
/* step options */
}
Adds single or multiple to the locals to describe the number of errors for pluralisation of error messages.
route name to template (without preceding slash)title to template if found in translations. Looked up in the order: pages.{route}.title -> fields.{firstFieldName}.label -> fields.{firstFieldName}.legend.intro to template if found in translations at pages.{route}.introAdd a locals object to step config to expose configurable key/value pairs in the template. Useful for generating template partials programmatically. These will override any locals provided further up the tree.
Steps config
'/step-name': {
locals: {
pageTitle: 'Page Title'
foo: 'bar'
}
}
Template
<h1>{{pageTitle}}</h1>
<div class="{{foo}}"></div>
Fields given in step config will be exposed to the template along with a mixin if defined in field config. This can be used with the renderField mixin to programmatically generate templates.
steps.js
steps: {
'step-1': {
fields: [
'field-1',
'field-2'
]
}
}
fields.js
fields: {
'field-1': {
mixin: 'input-text',
...
},
'field-2': {
mixin: 'radio-group',
...
}
}
exposed to templates in format:
fields: [{
key: 'field-1',
mixin: 'input-text'
}, {
key: 'field-2',
mixin: 'radio-group'
}]
Each step definition accepts a next property, the value of which is the next route in the journey. By default, when the form is successfully submitted, the next steps will load. However, there are times when it is necessary to fork from the current journey based on a users response to certain questions in a form. For such circumstances there exists the forks property.
In this example, when the submits the form, if the field called 'example-radio' has the value 'superman', the page at '/fork-page' will load, otherwise '/next-page' will be loaded.
'/my-page': {
next: '/next-page',
forks: [{
target: '/fork-page',
condition: {
field: 'example-radio',
value: 'superman'
}
}]
}
The condition property can also take a function. In the following example, if the field called 'name' is more than 30 characters in length, the page at '/fork-page' will be loaded.
'/my-page': {
next: '/next-page',
forks: [{
target: '/fork-page',
condition: function (req, res) {
return req.form.values['name'].length > 30;
}
}]
}
Forks is an array and therefore each fork is interrogated in order from top to bottom. The last fork whose condition is met will assign its target to the next page variable.
In this example, if the last condition resolves to true - even if the others also resolve to true - then the page at '/fork-page-three' will be loaded. The last condition to be met is always the fork used to determine the next step.
'/my-page': {
next: '/next-page',
forks: [{
target: '/fork-page-one',
condition: function (req, res) {
return req.form.values['name'].length > 30;
}
}, {
target: '/fork-page-two',
condition: {
field: 'example-radio',
value: 'superman'
}
}, {
target: '/fork-page-three',
condition: function (req, res) {
return typeof req.form.values['email'] === 'undefined';
}
}]
}
Accessed as from hof-controllers
var dateController = require('hof-controllers').date;
Extends from require('hof-controllers').base;
Validates the dates as a single item.
Date validators default to: required, numeric, format (DD-MM-YYYY), and future.
What the validators the date validates against can be overridden with the validate property on the date key field.
In this example, the 'my-date' fields will only validate if they contain non-numeric characters.
{
'my-date': {
validate: ['numeric']
}
}
Note: In the preceding example the field is not required and will not error on empty values.
validateFieldIf you want a shared date field to be required, but on a particular page wish it to be optional, validateField will accept a third parameter called isRequired.
This will allow the date field to be optional unless the user enters a value, in which case an appropriate message will be shown.
MyController.prototype.validateField = function validateField(keyToValidate, req) {
return DateController.prototype.validateField.call(this, keyToValidate, req, false);
};
D MMMM YYYY) date to the form values.A simple wrapper around require('hmpo-form-wizard').Error; to make it easier to extend and customise error behaviour on error.
To extend the functionality of a controller call the parent constructor and use node util to inherit the prototype;
this.dateKey is the value of the date field that the controller will process. The value of the this.dateKey must match the name of the date field.
Read more about date fields
var DateController = function DateController() {
this.dateKey = 'my-date';
Controller.apply(this, arguments);
};
util.inherits(DateController, Controller);
Extends the base controller's locals method to provide data in a format suitable for generating a summary table and email.
Accessed as confirm from hof-controllers.
var confirmController = require('hof-controllers').confirm;
Extends from require('hof-controllers').base
In step options
'/confirm': {
controller: require('hof-controllers').confirm,
fieldsConfig: require('./path/to/fields/config'),
emailConfig: require('../../config').email,
customerEmailField: 'email-address' // the id of the user's email address field
}
In config page template
{{#rows}}
{{> partials-summary-table}} <!-- {{name}}, {{value}}, {{origValue}} and {{step}} are available in this scope -->
{{/rows}}
This assumes all steps containing fields have a section - locals.section, this is used to group fields in the confirm table and the email.
Translations will be looked up automatically if located at the correct path. For section headers this is pages.{section}.summary which falls back to pages.{section}.header.
For fields the path is fields.{field}.summary which falls back firstly to fields.{field}.label then to fields.{field}.legend.
If the lookup fails the the section id or the field id are used.
The renderField mixin can be called in your template with the field to render as the scope. This will lookup the field.mixin in res.locals and call it passing the field key.
{{#fields}}
{{#renderField}}{{/renderField}}
{{/fields}}
renderField supports conditionally omitting fields if useWhen is passed in field config. useWhen accepts another field key String and checks the value is true, or an Object with the keys field and value. The field to check cannot appear on the same step - consider using the toggle property to show/hide a field on the same step.
'field-1': {
useWhen: 'field-2'
}
field-1 will only be included if field-2 value is true
'field-3': {
useWhen: {
field: 'field-4',
value: 'a-value'
}
}
field-3 will only be included if field-4 value is a-value
When a field on a multiple-step form is only to be included depending on the outcome of a previous answer. In the below example dependant-field is only included on step-2 if dependent-radio on step-1 is 'yes';
steps.js
{
'/step-1': {
fields: [
'dependent-radio'
]
},
'/step-2': {
fields: [
'dependant-field',
'regular-field'
]
}
}
fields.js
{
'dependent-radio': {
options: ['yes', 'no']
},
'dependant-field': {
useWhen: {
field: 'dependant-field',
value: 'yes'
}
},
'regular-field': {}
}
$ npm test
FAQs
A collection of controllers commonly used in HOF
The npm package hof-controllers receives a total of 65 weekly downloads. As such, hof-controllers popularity was classified as not popular.
We found that hof-controllers demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 20 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.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.