Skip to content

Commit

Permalink
feat: remove aria attributes and leave it to userland
Browse files Browse the repository at this point in the history
  • Loading branch information
logaretm committed Oct 11, 2020
1 parent bc0c5bc commit 365d825
Show file tree
Hide file tree
Showing 8 changed files with 3 additions and 75 deletions.
4 changes: 0 additions & 4 deletions docs/content/api/use-field.md
Expand Up @@ -85,10 +85,6 @@ type useField = (
errors: Ref<string[]>; // all error messages
errorMessage: Ref<string | undefined>; // the first error message
disabled: Ref<boolean>; // if the field is currently disabled
aria: Ref<{
'aria-invalid': 'true' | 'false';
'aria-describedBy': string;
}>;
reset: () => void; // resets errors and field meta
validate: () => Promise<ValidationResult>; // validates and updates the errors and field meta
handleChange: (e: Event) => void; // updates the value
Expand Down
2 changes: 1 addition & 1 deletion docs/content/guide/validation.md
Expand Up @@ -334,7 +334,7 @@ and if you would like, you could display all error messages for your fields by i

### Using ErrorMessage component

vee-validate offers an `<ErrorMessage />` component that displays your error messages in a convenient manner, as an added bonus vee-validate automatically adds some accessability attributes to both the `<Field />` and the associated `<ErrorMessage />` component.
vee-validate offers an `<ErrorMessage />` component that displays your error messages in a convenient manner.

```vue
<template>
Expand Down
3 changes: 1 addition & 2 deletions packages/core/src/ErrorMessage.ts
@@ -1,6 +1,6 @@
import { inject, h, defineComponent, computed, Ref } from 'vue';
import { FormErrorsSymbol } from './symbols';
import { normalizeChildren, genFieldErrorId } from './utils';
import { normalizeChildren } from './utils';

export const ErrorMessage = defineComponent({
props: {
Expand All @@ -26,7 +26,6 @@ export const ErrorMessage = defineComponent({

const tag = props.as;
const attrs = {
id: genFieldErrorId(props.name),
role: 'alert',
...ctx.attrs,
};
Expand Down
5 changes: 1 addition & 4 deletions packages/core/src/Field.ts
@@ -1,7 +1,7 @@
import { h, defineComponent, nextTick, toRef, SetupContext } from 'vue';
import { getConfig } from './config';
import { useField } from './useField';
import { normalizeChildren, isHTMLTag, hasCheckedAttr, isFileInput } from './utils';
import { normalizeChildren, hasCheckedAttr, isFileInput } from './utils';

export const Field = defineComponent({
name: 'Field',
Expand Down Expand Up @@ -49,7 +49,6 @@ export const Field = defineComponent({
handleInput,
reset,
meta,
aria,
checked,
} = useField(props.name, rules, {
validateOnMount: props.validateOnMount,
Expand Down Expand Up @@ -133,7 +132,6 @@ export const Field = defineComponent({

return {
field: fieldProps,
aria: aria.value,
meta,
errors: errors.value,
errorMessage: errorMessage.value,
Expand Down Expand Up @@ -165,7 +163,6 @@ export const Field = defineComponent({
{
...ctx.attrs,
...slotProps.field,
...(isHTMLTag(tag) ? slotProps.aria : {}),
},
children
);
Expand Down
13 changes: 0 additions & 13 deletions packages/core/src/useField.ts
Expand Up @@ -13,7 +13,6 @@ import {
extractLocators,
normalizeEventValue,
unwrap,
genFieldErrorId,
hasCheckedAttr,
getFromPath,
setInPath,
Expand Down Expand Up @@ -117,15 +116,12 @@ export function useField(name: string, rules: RuleExpression, opts?: Partial<Fie
return errors.value[0];
});

const aria = useAriAttrs(name, meta);

const field = {
name,
value: value,
meta,
errors,
errorMessage,
aria,
disabled,
type,
valueProp,
Expand Down Expand Up @@ -360,15 +356,6 @@ function useMeta() {
};
}

function useAriAttrs(fieldName: string, meta: Record<string, boolean>) {
return computed(() => {
return {
'aria-invalid': meta.failed ? 'true' : 'false',
'aria-describedBy': genFieldErrorId(fieldName),
};
});
}

/**
* Extracts the validation rules from a schema
*/
Expand Down
4 changes: 0 additions & 4 deletions packages/core/src/utils/common.ts
@@ -1,9 +1,5 @@
import { isEmptyContainer, isIndex, isNotNestedPath } from './assertions';

export function genFieldErrorId(fieldName: string): string {
return `v_${fieldName}_error`;
}

function cleanupNonNestedPath(path: string) {
if (isNotNestedPath(path)) {
return path.replace(/\[|\]/gi, '');
Expand Down
22 changes: 0 additions & 22 deletions packages/core/tests/ErrorMessage.spec.ts
Expand Up @@ -116,26 +116,4 @@ describe('<ErrorMessage />', () => {

expect(error.textContent).toBe(REQUIRED_MESSAGE);
});

test('is associated using aria-describeBy', async () => {
const wrapper = mountWithHoc({
components: {
ErrorMessage,
},
template: `
<VForm as="form">
<Field name="field" rules="required" as="input" />
<ErrorMessage name="field" as="span" />
<button>Validate</button>
</VForm>
`,
});

await flushPromises();
const error = wrapper.$el.querySelector('span');
const input = wrapper.$el.querySelector('input');

expect(input.getAttribute('aria-describedBy')).toBe(error.id);
});
});
25 changes: 0 additions & 25 deletions packages/core/tests/Field.spec.ts
Expand Up @@ -466,31 +466,6 @@ describe('<Field />', () => {
expect(error.textContent).toBe('');
});

test('generates aria invalid attribute', async () => {
const wrapper = mountWithHoc({
template: `
<div>
<Field name="field" rules="required" v-slot="{ aria, field }">
<input type="text" v-bind="{ ...field, ...aria }">
</Field>
</div>
`,
});

await flushPromises();
const input = wrapper.$el.querySelector('input');
expect(input.getAttribute('aria-invalid')).toBe('false');

setValue(input, '');
await flushPromises();

expect(input.getAttribute('aria-invalid')).toBe('true');

setValue(input, '1');
await flushPromises();
expect(input.getAttribute('aria-invalid')).toBe('false');
});

test('yup abortEarly is set by bails global option', async () => {
configure({
bails: false,
Expand Down

0 comments on commit 365d825

Please sign in to comment.