MessageBox
WORK IN PROGRESS - NOT YET PUBLISHED
A Meteor package for defining and getting validation error messages with reactive language selection.
Usage
Defining Messages
You can define global defaults if necessary:
1MessageBox.defaults({ 2 initialLanguage: 'en', 3 messages: { 4 en: { 5 errorString: '{{placeholder}}' || function, 6 errorString: { 7 _default: '{{placeholder}}' || function, 8 fieldName: '{{placeholder}}' || function, 9 } 10 }, 11 } 12});
Otherwise create your MessageBox
instance like this:
1const messageBox = new MessageBox({ 2 initialLanguage: 'en', 3 messages: { 4 en: { 5 errorType: '{{placeholder}}' || function, 6 errorType: { 7 _default: '{{placeholder}}' || function, 8 fieldName: '{{placeholder}}' || function, 9 } 10 }, 11 } 12});
And update the messages
object as necessary (for example if different packages are adding their own messages):
1messageBox.addMessages({ 2 en: { 3 errorType: '{{placeholder}}' || function, 4 errorType: { 5 _default: '{{placeholder}}' || function, 6 fieldName: '{{placeholder}}' || function, 7 } 8 }, 9});
addMessages
does a deep extend on the existing messages.
For any of the ways you can set messages, the message can be either a string or a function that returns a string. If it's a string, it may contain handlebars placeholders for anything in the error object or anything passed in the context
option of the message
function. If it's a function, it will receive a single context
argument that has all the same properties that are available as handlebars variables.
Example
1ForceField.defaults({ 2 initialLanguage: 'en', 3 messages: { 4 en: { 5 required: '{{label}} is required', 6 minString: '{{label}} must be at least {{min}} characters', 7 maxString: '{{label}} cannot exceed {{max}} characters', 8 minNumber: '{{label}} must be at least {{min}}', 9 maxNumber: '{{label}} cannot exceed {{max}}', 10 minNumberExclusive: '{{label}} must be greater than {{min}}', 11 maxNumberExclusive: '{{label}} must be less than {{max}}', 12 minDate: '{{label}} must be on or after {{min}}', 13 maxDate: '{{label}} cannot be after {{max}}', 14 badDate: '{{label}} is not a valid date', 15 minCount: 'You must specify at least {{minCount}} values', 16 maxCount: 'You cannot specify more than {{maxCount}} values', 17 noDecimal: '{{label}} must be an integer', 18 notAllowed: '{{value}} is not an allowed value', 19 expectedType: '{{label}} must be of type {{dataType}}', 20 regEx: function ({ 21 label, 22 type, 23 regExp, 24 }) { 25 // See if there's one where exp matches this expression 26 let msgObj; 27 if (regExp) { 28 msgObj = _.find(regExpMessages, (o) => o.exp && o.exp.toString() === regExp); 29 } 30 31 const regExpMessage = msgObj ? msgObj.msg : 'failed regular expression validation'; 32 33 return `${label} ${regExpMessage}`; 34 }, 35 keyNotInSchema: '{{name}} is not allowed by the schema', 36 }, 37 } 38});
Getting a Message
To get a message, you pass a single ValidationError
error to the message
function:
1Template.foo.events({ 2 'submit': (event, instance) => { 3 Meteor.call('method', (err) => { 4 if (ValidationError.is(err)) { 5 err.details.forEach((fieldError) => { 6 instance.state.set(`error-${fieldError.name}`: messageBox.message(fieldError)); 7 }); 8 } 9 }); 10 } 11});
See [https://github.com/meteor/validation-error] for details about the ValidationError
type.
By default, this function returns the message for the current language as set with initialLanguage
or setLanguage
, and will rerun when the language changes. However, you can instead specify a particular language:
1const message = messageBox.message(error, { 2 language: 'pl', 3});
Context
In the "Defining Messages" example, the placeholders like label
and min
must be in the error object or provided in the context option when calling messages
:
1const message = messageBox.message(error, { 2 context: { 3 label: getSomeLabelFor(error.name), 4 }, 5});
Changing the Message Language
1messageBox.setLanguage('en');
When you change the language, any call to messageBox.message()
that does not specify a language and is in a reactive context will rerun.