Skip to content

Commit

Permalink
feat: invoke generateMessage handler for local functions closes #2893
Browse files Browse the repository at this point in the history
  • Loading branch information
logaretm committed Sep 10, 2020
1 parent d37b746 commit e9fe773
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 16 deletions.
31 changes: 17 additions & 14 deletions packages/core/src/validate.ts
Expand Up @@ -12,9 +12,7 @@ interface FieldValidationContext {
name: string;
rules: Record<string, any>;
bails: boolean;
skipIfEmpty: boolean;
forceRequired: boolean;
crossTable: Record<string, any>;
formData: Record<string, any>;
}

interface ValidationOptions {
Expand All @@ -34,14 +32,11 @@ export async function validate(
options: ValidationOptions = {}
): Promise<ValidationResult> {
const shouldBail = options?.bails;
const skipIfEmpty = options?.skipIfEmpty;
const field: FieldValidationContext = {
name: options?.name || '{field}',
rules: normalizeRules(rules),
bails: shouldBail ?? true,
skipIfEmpty: skipIfEmpty ?? true,
forceRequired: false,
crossTable: options?.values || {},
formData: options?.values || {},
};

const result = await _validate(field, value);
Expand All @@ -56,20 +51,28 @@ export async function validate(
* Starts the validation process.
*/
async function _validate(field: FieldValidationContext, value: any) {
if (isYupValidator(field.rules)) {
return validateFieldWithYup(field, value);
}

// if a generic function, use it as the pipeline.
if (isCallable(field.rules)) {
const result = await field.rules(value);
const isValid = typeof result !== 'string' && result;
const message =
typeof result === 'string'
? result
: _generateFieldError({
field: field.name,
value,
form: field.formData,
});

return {
errors: !isValid ? [result as string] : [],
errors: !isValid ? [message] : [],
};
}

if (isYupValidator(field.rules)) {
return validateFieldWithYup(field, value);
}

const errors: ReturnType<typeof _generateFieldError>[] = [];
const rules = Object.keys(field.rules);
const length = rules.length;
Expand Down Expand Up @@ -129,11 +132,11 @@ async function _test(field: FieldValidationContext, value: any, rule: { name: st
throw new Error(`No such validator '${rule.name}' exists.`);
}

const params = fillTargetValues(rule.params, field.crossTable);
const params = fillTargetValues(rule.params, field.formData);
const ctx: FieldContext = {
field: field.name,
value,
form: field.crossTable,
form: field.formData,
rule,
};

Expand Down
28 changes: 28 additions & 0 deletions packages/core/tests/Field.spec.ts
Expand Up @@ -577,4 +577,32 @@ describe('<Field />', () => {
await flushPromises();
expect(input.value).toBe('455');
});

test('generateMessage is invoked with custom fn rules', async () => {
configure({
generateMessage: ({ field }) => `${field} is bad`,
});
const wrapper = mountWithHoc({
setup() {
return {
rules: () => false,
};
},
template: `
<div>
<Field :rules="rules" name="field" v-slot="{ field, errors }">
<input type="text" v-bind="field">
<p id="error">{{ errors[0] }}</p>
</Field>
</div>
`,
});

await flushPromises();
const input = wrapper.$el.querySelector('input');
const error = wrapper.$el.querySelector('#error');
setValue(input, '1234');
await flushPromises();
expect(error.textContent).toBe('field is bad');
});
});
5 changes: 4 additions & 1 deletion packages/i18n/src/index.ts
Expand Up @@ -30,6 +30,9 @@ class Dictionary {
public format(locale: string, ctx: FieldContext) {
let message!: ValidationMessageTemplate;
const { field, rule, form } = ctx;
if (!rule) {
return `${field} is not valid`;
}

// find if specific message for that field was specified.
message = this.container[locale]?.fields?.[field]?.[rule.name] || this.container[locale]?.messages?.[rule.name];
Expand All @@ -41,7 +44,7 @@ class Dictionary {

return isCallable(message)
? message(ctx)
: interpolate(message, { ...form, field: fieldName, params: ctx.rule.params });
: interpolate(message, { ...form, field: fieldName, params: rule.params });
}

public merge(dictionary: RootI18nDictionary) {
Expand Down
2 changes: 1 addition & 1 deletion packages/shared/types.ts
Expand Up @@ -2,7 +2,7 @@ export interface FieldContext {
field: string;
value: any;
form: Record<string, any>;
rule: {
rule?: {
name: string;
params?: Record<string, any> | any[];
};
Expand Down

0 comments on commit e9fe773

Please sign in to comment.