Skip to content

Commit

Permalink
Change 'errorMessages' to 'validationMessages' to match ASF.
Browse files Browse the repository at this point in the history
  • Loading branch information
dschnelldavis committed Nov 16, 2017
1 parent a24ce69 commit 3cbfd67
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 20 deletions.
26 changes: 20 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,21 @@ For basic use, after loading JsonSchemaFormModule as described above, to display

Where the `framework` is the name of the display framework to use (`bootstrap-3`, `bootstrap-4`, `material-design`, or `no-framework`), `schema` is a valid JSON schema object, and `onSubmit` calls a function to process the submitted JSON form data. If you don't already have your own schemas, you can find a bunch of samples to test with in the `src/demo/assets/example-schemas` folder, as described above.

(Note: Setting `loadExternalAssets="true"` will automatically load any additional assets needed by the display framework. It is useful when you are trying out this library, but should be removed in production sites, which should instead load all required assets separately. For full details see 'Changing or adding frameworks', below.)
Setting `loadExternalAssets="true"` will automatically load any additional assets needed by the display framework. It is useful when you are trying out this library, but should be removed in production sites, which should instead load all required assets separately. For full details see 'Changing or adding frameworks', below.

Note: If you prefer brackets around all your attributes, the following is functionally equivalent:

```html
<json-schema-form
[framework]="'bootstrap-3'"
[loadExternalAssets]="true"
[schema]="yourJsonSchema"
(onSubmit)="yourOnSubmitFn($event)">
</json-schema-form>
```

If you use this syntax, make sure to include the nested quotes (`"'` and `'"`) around the framework name.


### Data-only mode

Expand Down Expand Up @@ -282,20 +296,20 @@ To set messages for individual form controls, add them to that control's node in
let yourFormLayout = [
{ key: 'name',
title: 'Enter your name',
errorMessages: {
validationMessages: {
// Put your error messages for the 'name' field here
}
},
{ type: 'submit', title: 'Submit' }
]
```

To set messages for the entire form, add them to the form options, inside the defautWidgetOptions errorMessages object, like this:
To set messages for the entire form, add them to the form options, inside the defautWidgetOptions validationMessages object, like this:

```javascript
let yourFormOptions = {
defautWidgetOptions: {
errorMessages: {
validationMessages: {
// Put your error messages for the entire form here
}
}
Expand All @@ -304,15 +318,15 @@ let yourFormOptions = {

#### How to format error messages

The errorMessages object—in either a layout node or the form options—contains the names of each error message you want to set as keys, and the corresponding messages as values. Messages may be in any of the following formats:
The validationMessages object—in either a layout node or the form options—contains the names of each error message you want to set as keys, and the corresponding messages as values. Messages may be in any of the following formats:

* String: A plain text message, which is always the same.
* String template: A text message that includes Angular template-style {{variables}}, which will be be replaced with values from the returned error object.
* Function: A JavaScript function which accepts the error object as input, and returns a string error message.

Here are examples of all three error message types:
```javascript
errorMessages: {
validationMessages: {

// String error message
required: 'This field is required.',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ export class Bootstrap3FrameworkComponent implements OnInit, OnChanges {
this.options.helpBlock = status === 'INVALID' &&
this.options.enableErrorState && this.formControl.errors &&
(this.formControl.dirty || this.options.feedbackOnRender) ?
this.jsf.formatErrors(this.formControl.errors, this.options.errorMessages) :
this.jsf.formatErrors(this.formControl.errors, this.options.validationMessages) :
this.options.description || this.options.help || null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ export class Bootstrap4FrameworkComponent implements OnInit, OnChanges {
this.options.helpBlock = status === 'INVALID' &&
this.options.enableErrorState && this.formControl.errors &&
(this.formControl.dirty || this.options.feedbackOnRender) ?
this.jsf.formatErrors(this.formControl.errors, this.options.errorMessages) :
this.jsf.formatErrors(this.formControl.errors, this.options.validationMessages) :
this.options.description || this.options.help || null;
}

Expand Down
26 changes: 14 additions & 12 deletions src/lib/src/json-schema-form.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export class JsonSchemaFormService {
disabled: false, // Set control as disabled? (not editable, and excluded from output)
readonly: false, // Set control as read only? (not editable, but included in output)
returnEmptyFields: true, // return values for fields that contain no data?
errorMessages: { // Default error messages
validationMessages: { // Default error messages
required: 'This field is required.',
minLength: 'Must be {{minimumLength}} characters or longer (current length: {{currentLength}})',
maxLength: 'Must be {{maximumLength}} characters or shorter (current length: {{currentLength}})',
Expand Down Expand Up @@ -246,7 +246,7 @@ export class JsonSchemaFormService {
compiledErrors[error.dataPath].push(error.message);
});
return compiledErrors;
}
};
this.ajvErrors = this.validateFormData.errors;
this.validationErrors = compileErrors(this.validateFormData.errors);
if (updateSubscriptions) {
Expand Down Expand Up @@ -429,12 +429,12 @@ export class JsonSchemaFormService {
ctx.controlValue = ctx.formControl.value;
ctx.controlDisabled = ctx.formControl.disabled;
ctx.options.errorMessage = ctx.formControl.status === 'VALID' ? null :
this.formatErrors(ctx.formControl.errors, ctx.options.errorMessages);
this.formatErrors(ctx.formControl.errors, ctx.options.validationMessages);
ctx.options.showErrors = this.formOptions.validateOnRender === true ||
(this.formOptions.validateOnRender === 'auto' && hasValue(ctx.controlValue));
ctx.formControl.statusChanges.subscribe(status =>
ctx.options.errorMessage = status === 'VALID' ? null :
this.formatErrors(ctx.formControl.errors, ctx.options.errorMessages)
this.formatErrors(ctx.formControl.errors, ctx.options.validationMessages)
);
ctx.formControl.valueChanges.subscribe(value => {
if (!_.isEqual(ctx.controlValue, value)) { ctx.controlValue = value }
Expand All @@ -450,9 +450,9 @@ export class JsonSchemaFormService {
return ctx.boundControl;
}

formatErrors(errors: any, errorMessages: any = {}): string {
formatErrors(errors: any, validationMessages: any = {}): string {
if (isEmpty(errors)) { return null; }
if (!isObject(errorMessages)) { errorMessages = {}; }
if (!isObject(validationMessages)) { validationMessages = {}; }
const addSpaces = string => string[0].toUpperCase() + (string.slice(1) || '')
.replace(/([a-z])([A-Z])/g, '$1 $2').replace(/_/g, ' ');
const formatError = (error) => typeof error === 'object' ?
Expand All @@ -467,20 +467,22 @@ export class JsonSchemaFormService {
// Hide 'required' error, unless it is the only one
.filter(errorKey => errorKey !== 'required' || Object.keys(errors).length === 1)
.map(errorKey =>
// If validationMessages is a string, return it
typeof validationMessages === 'string' ? validationMessages :
// If custom error message is a function, return function result
typeof errorMessages[errorKey] === 'function' ?
errorMessages[errorKey](errors[errorKey]) :
typeof validationMessages[errorKey] === 'function' ?
validationMessages[errorKey](errors[errorKey]) :
// If custom error message is a string, replace placeholders and return
typeof errorMessages[errorKey] === 'string' ?
typeof validationMessages[errorKey] === 'string' ?
// Does error message have any {{property}} placeholders?
errorMessages[errorKey].indexOf('{{') === -1 ?
errorMessages[errorKey] :
validationMessages[errorKey].indexOf('{{') === -1 ?
validationMessages[errorKey] :
// Replace {{property}} placeholders with values
Object.keys(errors[errorKey])
.reduce((errorMessage, errorProperty) => errorMessage.replace(
new RegExp('{{' + errorProperty + '}}', 'g'),
errors[errorKey][errorProperty]
), errorMessages[errorKey]) :
), validationMessages[errorKey]) :
// If no custom error message, return formatted error data instead
addSpaces(errorKey) + ' Error: ' + formatError(errors[errorKey])
).join('<br>');
Expand Down
1 change: 1 addition & 0 deletions src/lib/src/shared/form-group.functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,7 @@ export function formatFormData(
}
});
}

// Finish incomplete 'date-time' entries
if (dataMap.get(genericPointer).get('schemaFormat') === 'date-time') {
// "2000-03-14T01:59:26.535" -> "2000-03-14T01:59:26.535Z" (add "Z")
Expand Down
34 changes: 34 additions & 0 deletions src/lib/src/shared/layout.functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,40 @@ export function buildLayout(jsf, widgetLibrary) {
newNode.options.title = fixTitle(newNode.name);
}
}
// Convert Angular Schema Form (AngularJS) 'validationMessage' to
// Angular JSON Schema Form 'validationMessages'
// TV4 codes from https://github.com/geraintluff/tv4/blob/master/source/api.js
if (!hasOwn(newNode.options, 'validationMessages') && hasOwn(newNode.options, 'validationMessage')) {
if (typeof newNode.options.validationMessage === 'string') {
newNode.options.validationMessages = newNode.options.validationMessage;
} else {
newNode.options.validationMessages = {};
Object.keys(newNode.options.validationMessage).forEach(key => {
const code = key + '';
const newKey =
code === '0' ? 'type' :
code === '1' ? 'enum' :
code === '100' ? 'multipleOf' :
code === '101' ? 'minimum' :
code === '102' ? 'exclusiveMinimum' :
code === '103' ? 'maximum' :
code === '104' ? 'exclusiveMaximum' :
code === '200' ? 'minLength' :
code === '201' ? 'maxLength' :
code === '202' ? 'pattern' :
code === '300' ? 'minProperties' :
code === '301' ? 'maxProperties' :
code === '302' ? 'required' :
code === '304' ? 'dependencies' :
code === '400' ? 'minItems' :
code === '401' ? 'maxItems' :
code === '402' ? 'uniqueItems' :
code === '500' ? 'format' : code + '';
newNode.options.validationMessages[newKey] = newNode.options.validationMessage[key];
});
}
delete newNode.options.validationMessage;
}
} else if (JsonPointer.isJsonPointer(layoutItem)) {
newNode.dataPointer = layoutItem;
} else if (isString(layoutItem)) {
Expand Down

0 comments on commit 3cbfd67

Please sign in to comment.