Skip to content

Commit

Permalink
feat: form group context and path prefixes
Browse files Browse the repository at this point in the history
  • Loading branch information
logaretm committed Aug 13, 2024
1 parent 1fb447e commit b3810d6
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 6 deletions.
8 changes: 7 additions & 1 deletion packages/core/src/form/useFormField.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { FormContext, FormKey } from './useForm';
import { Arrayable, Getter } from '../types';
import { useSyncModel } from '../reactivity/useModelSync';
import { cloneDeep, isEqual, normalizeArrayable } from '../utils/common';
import { FormGroupKey } from '../useFormGroup';

interface FormFieldOptions<TValue = unknown> {
path: MaybeRefOrGetter<string | undefined> | undefined;
Expand All @@ -38,7 +39,12 @@ export type FormField<TValue> = {

export function useFormField<TValue = unknown>(opts?: Partial<FormFieldOptions<TValue>>): FormField<TValue> {
const form = inject(FormKey, null);
const getPath = () => toValue(opts?.path);
const formGroup = inject(FormGroupKey, null);
const getPath = () => {
const path = toValue(opts?.path);

return formGroup ? formGroup.prefixPath(path) : path;
};
const { fieldValue, pathlessValue, setValue } = useFieldValue(getPath, form, opts?.initialValue);
const { isTouched, pathlessTouched, setTouched } = useFieldTouched(getPath, form);
const { errors, setErrors, isValid, errorMessage, pathlessValidity } = useFieldValidity(getPath, form);
Expand Down
39 changes: 38 additions & 1 deletion packages/core/src/useFormGroup/useFormGroup.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
import { computed, createBlock, defineComponent, Fragment, openBlock, Ref, shallowRef, toValue, VNode } from 'vue';
import {
computed,
createBlock,
defineComponent,
Fragment,
InjectionKey,
openBlock,
provide,
Ref,
shallowRef,
toValue,
VNode,
} from 'vue';
import { useLabel } from '../a11y/useLabel';
import { FieldTypePrefixes } from '../constants';
import { AriaLabelableProps, AriaLabelProps, FormObject, Reactivify, TypedSchema } from '../types';
import { normalizeProps, useUniqId, withRefCapture } from '../utils/common';

export interface FormGroupProps<TInput extends FormObject = FormObject, TOutput extends FormObject = TInput> {
name?: string;
label?: string;
schema?: TypedSchema<TInput, TOutput>;
}
Expand All @@ -14,6 +27,12 @@ interface GroupProps extends AriaLabelableProps {
role?: 'group';
}

interface FormGroupContext {
prefixPath: (path: string | undefined) => string | undefined;
}

export const FormGroupKey: InjectionKey<FormGroupContext> = Symbol('FormGroup');

export function useFormGroup<TInput extends FormObject = FormObject, TOutput extends FormObject = TInput>(
_props: Reactivify<FormGroupProps<TInput, TOutput>>,
elementRef?: Ref<HTMLElement>,
Expand Down Expand Up @@ -44,6 +63,14 @@ export function useFormGroup<TInput extends FormObject = FormObject, TOutput ext

const FormGroup = createInlineFormGroupComponent({ groupProps, labelProps });

const ctx: FormGroupContext = {
prefixPath(path: string | undefined) {
return prefixPath(toValue(props.name), path);
},
};

provide(FormGroupKey, ctx);

return {
groupRef,
labelProps,
Expand Down Expand Up @@ -76,3 +103,13 @@ function createInlineFormGroupComponent({ groupProps, labelProps }: Reactivify<I
};
};
}

function prefixPath(prefix: string | undefined, path: string | undefined) {
if (!path) {
return path;
}

prefix = prefix ? `${prefix}.` : '';

return `${prefix}${path}`;
}
11 changes: 7 additions & 4 deletions packages/playground/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@
<div v-bind="groupProps">
<div v-bind="labelProps">Shipping Address</div>

<InputText label="deep" name="some.deep.path" />
<InputText label="arr" name="some.array.0.path" />
<InputText label="deep" name="deep.path" />
<InputText label="arr" name="array.0.path" />
</div>
</FormGroup>

<pre>{{ values }}</pre>
<pre>{{ getErrors() }}</pre>
</div>
</template>

Expand All @@ -18,9 +21,9 @@ import { useForm, useFormGroup } from '@formwerk/core';
import { defineSchema } from '@formwerk/schema-zod';
import { z } from 'zod';
const { FormGroup } = useFormGroup({ label: 'Shipping Information' });
const { FormGroup } = useFormGroup({ name: 'some.deep', label: 'Shipping Information' });
const form = useForm({
const { getErrors, values } = useForm({
schema: defineSchema(
z.object({
some: z.object({
Expand Down

0 comments on commit b3810d6

Please sign in to comment.