Skip to content

Commit

Permalink
feat(BInput): support json value
Browse files Browse the repository at this point in the history
  • Loading branch information
ido-pluto committed Jun 29, 2024
1 parent 674a680 commit 16701d6
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 13 deletions.
17 changes: 17 additions & 0 deletions examples/simple-form/src/pages/state-json-upload.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
import { BButton, BInput, Bind, BindForm } from '@astro-utils/forms/forms.js';
import Layout from '../layouts/Layout.astro';
const bind = Bind({json: {a: 2}});
function onSubmit() {
console.log(bind.json);
}
---

<Layout title='Test Select'>
<BindForm bind={bind} key='page'>
<BInput type='json' name=`json`/>
<BButton onClick={onSubmit}>Submit</BButton>
</BindForm>
</Layout>
21 changes: 20 additions & 1 deletion packages/forms/src/components-control/form-utils/parse.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { AstroGlobal } from 'astro';
import { z } from 'zod';
import { ZodIssueCode, z } from 'zod';
import { getFormMultiValue } from '../../form-tools/post.js';
import AboutFormName from './about-form-name.js';

Expand Down Expand Up @@ -71,6 +71,25 @@ export function parseDate(about: AboutFormName, type: DateTypes, min?: string |
about.catchParse(date);
}

export function parseJSON(about: AboutFormName) {
const EMPTY_OBJECT = {};

about.catchParse(z.string()
.transform((str, ctx): z.infer<ReturnType<any>> => {
try {
return JSON.parse(str, (key: string, value: any) => {
if (EMPTY_OBJECT[key] !== undefined) {
return;
}
return value;
});
} catch (e) {
ctx.addIssue({ code: ZodIssueCode.custom, message: 'Invalid JSON' });
return z.NEVER;
}
}));
}

export function parseEmail(about: AboutFormName) {
about.catchParse(z.string().email());
}
Expand Down
29 changes: 20 additions & 9 deletions packages/forms/src/components-control/input-parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import { getFormValue } from '../form-tools/post.js';
import AboutFormName from './form-utils/about-form-name.js';
import type HTMLInputRadioPlugin from './form-utils/bind-form-plugins/input-radio.js';
import { BindForm } from './form-utils/bind-form.js';
import { parseCheckbox, parseColor, parseDate, parseEmail, parseFiles, parseNumber, parseURL } from './form-utils/parse.js';
import { parseCheckbox, parseColor, parseDate, parseEmail, parseFiles, parseJSON, parseNumber, parseURL } from './form-utils/parse.js';
import { validateFunc, validateRequire, validateStringPatters } from './form-utils/validate.js';
import {getProperty} from 'dot-prop';
import { ZodType } from 'zod';

const OK_NOT_STRING_VALUE = ['checkbox', 'file'];
const OK_INPUT_VALUE_NULL = ['checkbox'];
Expand Down Expand Up @@ -35,7 +36,7 @@ type InputTypes =
| 'url'
| 'week';

type ExtendedInputTypes = InputTypes | 'int';
type ExtendedInputTypes = InputTypes | 'int' | 'json';

export async function getInputValue(astro: AstroGlobal, bindId: string, bind: BindForm<any>) {
const { value, name, readonly } = astro.props;
Expand Down Expand Up @@ -66,8 +67,12 @@ export async function validateFormInput(astro: AstroGlobal, bind: BindForm<any>,

// specific validation by type / function
validateByInputType(astro, aboutInput, bind);
if (!aboutInput.hadError && typeof validate == 'function') {
await validateFunc(aboutInput, validate);
if (!aboutInput.hadError) {
if(typeof validate == 'function'){
await validateFunc(aboutInput, validate);
} else if(validate instanceof ZodType){
aboutInput.catchParse(validate);
}
}

aboutInput.setValue();
Expand Down Expand Up @@ -112,6 +117,10 @@ function validateByInputType(astro: AstroGlobal, aboutInput: AboutFormName, bind
parseURL(aboutInput);
break;

case 'json':
parseJSON(aboutInput);
break;

case 'file':
parseFiles(aboutInput, astro, multiple, readonly);
break;
Expand All @@ -129,7 +138,7 @@ function toDateTimeLocal(date: Date) {
}


function stringifyDate(date?: Date | string, type?: ExtendedInputTypes) {
function stringifyCustomValue(date?: Date | string, type?: ExtendedInputTypes) {
if (typeof date === 'string' || !date) {
return date;
}
Expand All @@ -145,15 +154,17 @@ function stringifyDate(date?: Date | string, type?: ExtendedInputTypes) {
return toDateTimeLocal(date).slice(0, 7);
case 'week':
return formatToDateWeek(date);
case 'json':
return JSON.stringify(date);
}

return date;
}

export function inputReturnValueAttr(astro: AstroGlobal, bind: BindForm<any>) {
const value = stringifyDate(getProperty(bind, astro.props.name, astro.props.value), astro.props.type);
const min = stringifyDate(astro.props.min, astro.props.type);
const max = stringifyDate(astro.props.max, astro.props.type);
const value = stringifyCustomValue(getProperty(bind, astro.props.name, astro.props.value), astro.props.type);
const min = stringifyCustomValue(astro.props.min, astro.props.type);
const max = stringifyCustomValue(astro.props.max, astro.props.type);

switch (astro.props.type as ExtendedInputTypes) {
case 'checkbox':
Expand All @@ -174,7 +185,7 @@ function formatToDateWeek(date: Date): string {
}


export function caseTypes(type: ExtendedInputTypes): { type: InputTypes; } & { [key: string]: string; } {
export function caseTypes(type: ExtendedInputTypes): { type: ExtendedInputTypes; } & { [key: string]: string; } {
if (type == 'int') {
return {
type: 'number',
Expand Down
5 changes: 3 additions & 2 deletions packages/forms/src/components/form/BInput.astro
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import { validateFrom } from '../../form-tools/csrf.js';
import { ModifyDeep } from '../../utils.js';
import { addOnSubmitClickEvent } from '../../form-tools/events.js';
import { MissingNamePropError } from '../../errors/MissingNamePropError.js';
import { ZodType } from 'zod';
type inputTypes = astroHTML.JSX.InputHTMLAttributes['type'] | 'int';
type inputTypes = astroHTML.JSX.InputHTMLAttributes['type'] | 'int' | 'json';
interface ModifyInputProps {
type?: inputTypes;
Expand All @@ -22,7 +23,7 @@ interface ModifyInputProps {
export interface Props<T extends keyof JSX.IntrinsicElements | React.JSXElementConstructor<any>> extends Partial<ModifyDeep<astroHTML.JSX.InputHTMLAttributes, ModifyInputProps>> {
name: string;
errorMessage?: string;
validate?: Function;
validate?: Function | ZodType;
as?: T;
props?: React.ComponentProps<T>;
}
Expand Down
3 changes: 2 additions & 1 deletion packages/forms/src/components/form/BTextarea.astro
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { ModifyDeep } from '../../utils.js';
import { getProperty } from 'dot-prop';
import { addOnSubmitClickEvent } from '../../form-tools/events.js';
import { MissingNamePropError } from '../../errors/MissingNamePropError.js';
import { ZodType } from 'zod';
interface ModifyInputProps {
minlength?: number;
Expand All @@ -15,7 +16,7 @@ interface ModifyInputProps {
export interface Props<T extends keyof JSX.IntrinsicElements | React.JSXElementConstructor<any>> extends Partial<ModifyDeep<astroHTML.JSX.TextareaHTMLAttributes, ModifyInputProps>> {
name: string;
errorMessage?: string;
validate?: Function;
validate?: Function | ZodType;
as?: T;
props?: React.ComponentProps<T>;
onSubmitClick?: string;
Expand Down

0 comments on commit 16701d6

Please sign in to comment.