diff --git a/API.md b/API.md
index 3021dd36..4fb4592b 100644
--- a/API.md
+++ b/API.md
@@ -271,11 +271,13 @@ The message that will show when the form input component is invalid. It will be
name="email"
validations={{
isEmail: true,
- maxLength: 50
+ maxLength: 50,
+ someCustomValidation: [1, 2, 3]
}}
validationErrors={{
isEmail: 'You have to type valid email',
- maxLength: 'You can not type in more than 50 characters'
+ maxLength: 'You can not type in more than {0} characters',
+ someCustomValidation: '{0} + {1} = {2}'
}}
/>
```
diff --git a/examples/dynamic-form-fields/app.js b/examples/dynamic-form-fields/app.js
index 9549c4a0..c7b4269f 100644
--- a/examples/dynamic-form-fields/app.js
+++ b/examples/dynamic-form-fields/app.js
@@ -7,6 +7,15 @@ import MySelect from './../components/Select';
import MyRadioGroup from './../components/RadioGroup';
import MyMultiCheckboxSet from './../components/MultiCheckboxSet';
+const validationErrors = {
+ 'isEmail': 'The field must contain a valid email address',
+ 'isNumeric': 'The field must contain only numbers',
+ 'isAlphanumeric': 'The field must only contain alpha-numeric characters',
+ 'equals': 'The field must be equal to {0}',
+ 'minLength': 'The field must be at least {0} characters in length',
+ 'maxLength': 'The field must not exceed {0} characters in length'
+};
+
const Fields = props => {
function onRemove(pos) {
return event => {
@@ -27,6 +36,7 @@ const Fields = props => {
title={field.validations ? JSON.stringify(field.validations) : 'No validations'}
required={field.required}
validations={field.validations}
+ validationErrors={validationErrors}
/>
) :
(
@@ -35,6 +45,7 @@ const Fields = props => {
title={field.validations ? JSON.stringify(field.validations) : 'No validations'}
required={field.required}
validations={field.validations}
+ validationErrors={validationErrors}
options={[
{title: '123', value: '123'},
{title: 'some long text', value: 'some long text'},
@@ -86,7 +97,6 @@ const App = React.createClass({
cmp={(a, b) => JSON.stringify(a) === JSON.stringify(b)}
items={[
{isEmail: true},
- {isEmptyString: true},
{isNumeric: true},
{isAlphanumeric: true},
{equals: 5},
diff --git a/src/main.js b/src/main.js
index 7edb786d..e6419534 100644
--- a/src/main.js
+++ b/src/main.js
@@ -255,7 +255,7 @@ Formsy.Form = React.createClass({
// the component defines an explicit validate function
if (typeof component.validate === "function") {
- validationResults.failed = component.validate() ? [] : ['failed'];
+ validationResults.failed = component.validate() ? [] : [{ method: 'failed' }];
}
var isRequired = Object.keys(component._requiredValidations).length ? !!requiredResults.success.length : false;
@@ -285,7 +285,13 @@ Formsy.Form = React.createClass({
if (validationResults.failed.length) {
return validationResults.failed.map(function(failed) {
- return validationErrors[failed] ? validationErrors[failed] : validationError;
+ var errorMessage = validationErrors[failed.method] ? validationErrors[failed.method] : validationError;
+
+ failed.args && [].concat(failed.args).forEach((arg, i) => {
+ errorMessage = errorMessage.replace(new RegExp('\\{' + i + '\\}', 'g'), arg);
+ });
+
+ return errorMessage;
}).filter(function(x, pos, arr) {
// Remove duplicates
return arr.indexOf(x) === pos;
@@ -319,9 +325,9 @@ Formsy.Form = React.createClass({
var validation = validations[validationMethod](currentValues, value);
if (typeof validation === 'string') {
results.errors.push(validation);
- results.failed.push(validationMethod);
+ results.failed.push({ method: validationMethod });
} else if (!validation) {
- results.failed.push(validationMethod);
+ results.failed.push({ method: validationMethod });
}
return;
@@ -329,9 +335,9 @@ Formsy.Form = React.createClass({
var validation = validationRules[validationMethod](currentValues, value, validations[validationMethod]);
if (typeof validation === 'string') {
results.errors.push(validation);
- results.failed.push(validationMethod);
+ results.failed.push({ method: validationMethod, args: validations[validationMethod] });
} else if (!validation) {
- results.failed.push(validationMethod);
+ results.failed.push({ method: validationMethod, args: validations[validationMethod] });
} else {
results.success.push(validationMethod);
}
diff --git a/tests/Element-spec.js b/tests/Element-spec.js
index 38b93acc..24813813 100644
--- a/tests/Element-spec.js
+++ b/tests/Element-spec.js
@@ -399,6 +399,39 @@ export default {
},
+ 'should validation parameters passed to validation errors messages': function (test) {
+
+ const TestForm = React.createClass({
+ render() {
+ return (
+
+
+
+ );
+ }
+ });
+ const form = TestUtils.renderIntoDocument();
+
+ const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
+ const input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
+ TestUtils.Simulate.change(input, {target: {value: 'xx'}});
+ test.equal(inputComponent.getErrorMessage(), 'The field must be at least 3 characters in length');
+ TestUtils.Simulate.change(input, {target: {value: 'xxxxxx'}});
+ test.equal(inputComponent.getErrorMessage(), 'The field must not exceed 5 characters in length');
+
+ test.done();
+
+ },
+
'should not be valid if it is required and required rule is true': function (test) {
const TestForm = React.createClass({