Skip to content

Commit

Permalink
feat: implemented disabled prop
Browse files Browse the repository at this point in the history
  • Loading branch information
logaretm committed May 14, 2020
1 parent 1b9bded commit 88bf28e
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 33 deletions.
4 changes: 4 additions & 0 deletions packages/core/src/Provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ export const ValidationProvider = defineComponent({
setup(props, ctx) {
const fieldName = props.name;
const $form = inject('$_veeObserver', undefined) as FormController | undefined;
// FIXME: is this right?
const disabled = computed(() => props.disabled as boolean);
const {
errors,
failedRules,
Expand All @@ -54,6 +56,7 @@ export const ValidationProvider = defineComponent({
form: $form,
immediate: props.immediate as boolean,
bails: props.bails as boolean,
disabled,
});

const unwrappedMeta = useRefsObjToComputed(meta);
Expand All @@ -62,6 +65,7 @@ export const ValidationProvider = defineComponent({
return {
field: {
name: fieldName,
disabled: props.disabled,
onInput: handleChange,
onChange: handleChange,
'onUpdate:modelValue': handleChange,
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export interface FieldComposite {
onBlur(e?: any): void;
value: Ref<any>;
name: MaybeReactive<string>;
disabled: MaybeReactive<boolean>;
failedRules: Ref<Record<string, string>>;
errors: Ref<string[]>;
errorMessage: Ref<string | undefined>;
Expand All @@ -95,7 +96,7 @@ export interface FormController {
fields: any;
}

export type MaybeReactive<T> = Ref<T> | T;
export type MaybeReactive<T> = Ref<T> | ComputedRef<T> | T;

export type SubmissionHandler = (values: Record<string, any>) => any;

Expand Down
5 changes: 4 additions & 1 deletion packages/core/src/useField.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { normalizeRules, extractLocators, normalizeEventValue, unwrap } from './

interface FieldOptions {
value: Ref<any>;
disabled: MaybeReactive<boolean>;
immediate?: boolean;
bails?: boolean;
form?: FormController;
Expand All @@ -28,7 +29,7 @@ export function useField(
rules: RuleExpression,
opts?: Partial<FieldOptions>
): FieldComposite {
const { value, form, immediate, bails } = normalizeOptions(opts);
const { value, form, immediate, bails, disabled } = normalizeOptions(opts);
const { meta, errors, failedRules, onBlur, handleChange, reset, patch } = useValidationState(value);
let schemaValidation: GenericValidateFunction;
const normalizedRules = computed(() => {
Expand Down Expand Up @@ -87,6 +88,7 @@ export function useField(
validate: runValidationWithMutation,
handleChange,
onBlur,
disabled,
__setRules(fn: GenericValidateFunction) {
schemaValidation = fn;
},
Expand All @@ -106,6 +108,7 @@ function normalizeOptions(opts: Partial<FieldOptions> | undefined): FieldOptions
immediate: false,
bails: true,
rules: '',
disabled: false,
});

if (!opts) {
Expand Down
70 changes: 39 additions & 31 deletions packages/core/src/useForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,20 @@ import { computed, ref, Ref } from 'vue';
import { Flag, FormController, SubmissionHandler, GenericValidateFunction, FieldComposite } from './types';
import { unwrap } from './utils/refs';

const mergeStrategies: Record<Flag, 'every' | 'some'> = {
valid: 'every',
invalid: 'some',
dirty: 'some',
pristine: 'every',
touched: 'some',
untouched: 'every',
pending: 'some',
validated: 'every',
changed: 'some',
passed: 'every',
failed: 'some',
};

function computeMeta(fields: Ref<any[]>) {
const flags: Flag[] = Object.keys(mergeStrategies) as Flag[];

return flags.reduce((acc, flag: Flag) => {
acc[flag] = computed(() => {
const mergeMethod = mergeStrategies[flag];
return fields.value[mergeMethod](field => field.meta[flag]);
});

return acc;
}, {} as Record<Flag, Ref<boolean>>);
}

interface FormOptions {
validationSchema: Record<string, GenericValidateFunction>;
}

export function useForm(opts?: FormOptions) {
const fields: Ref<any[]> = ref([]);
const fieldsById: Record<string, any> = {};

const activeFields = computed(() => {
return fields.value.filter(field => !unwrap(field.disabled));
});

const values = computed(() => {
return fields.value.reduce((acc: any, field: any) => {
return activeFields.value.reduce((acc: any, field: any) => {
acc[field.name] = field.value;

return acc;
Expand Down Expand Up @@ -70,7 +48,7 @@ export function useForm(opts?: FormOptions) {

const validate = async () => {
const results = await Promise.all(
fields.value.map((f: any) => {
activeFields.value.map((f: any) => {
return f.validate();
})
);
Expand All @@ -79,7 +57,7 @@ export function useForm(opts?: FormOptions) {
};

const errors = computed(() => {
return fields.value.reduce((acc: Record<string, string[]>, field) => {
return activeFields.value.reduce((acc: Record<string, string[]>, field) => {
acc[field.name] = field.errorMessage;

return acc;
Expand All @@ -90,9 +68,11 @@ export function useForm(opts?: FormOptions) {
fields.value.forEach((f: any) => f.reset());
};

const meta = useFormMeta(fields);

return {
errors,
meta: computeMeta(fields),
meta,
form: controller,
values,
validate,
Expand All @@ -113,3 +93,31 @@ export function useForm(opts?: FormOptions) {
},
};
}

const MERGE_STRATEGIES: Record<Flag, 'every' | 'some'> = {
valid: 'every',
invalid: 'some',
dirty: 'some',
pristine: 'every',
touched: 'some',
untouched: 'every',
pending: 'some',
validated: 'every',
changed: 'some',
passed: 'every',
failed: 'some',
};

function useFormMeta(fields: Ref<any[]>) {
const flags: Flag[] = Object.keys(MERGE_STRATEGIES) as Flag[];

return flags.reduce((acc, flag: Flag) => {
acc[flag] = computed(() => {
const mergeMethod = MERGE_STRATEGIES[flag];

return fields.value[mergeMethod](field => field.meta[flag]);
});

return acc;
}, {} as Record<Flag, Ref<boolean>>);
}
36 changes: 36 additions & 0 deletions packages/core/tests/observer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,39 @@ test('handles reset', async () => {
expect(error.textContent).toBe('');
expect(isReset).toBe(true);
});

test('disabled fields do not participate in validation', async () => {
let isInObject = false;
const wrapper = mountWithHoc({
setup() {
return {
disabled: false,
submit: (values: Record<string, any>) => {
isInObject = 'field' in values;
},
};
},
template: `
<ValidationObserver @submit="submit" as="form">
<ValidationProvider rules="required" name="field" as="input" :disabled="disabled"/>
<button id="submit">Submit</button>
</ValidationObserver>
`,
});

const input = wrapper.$el.querySelector('input');
setValue(input, '123');
const button = wrapper.$el.querySelector('#submit');

button.click();
await flushPromises();

expect(isInObject).toBe(true);

(wrapper as any).disabled = true;
button.click();
await flushPromises();

expect(isInObject).toBe(false);
});

0 comments on commit 88bf28e

Please sign in to comment.