fix json field

This commit is contained in:
dswbx
2025-10-28 16:00:58 +01:00
parent e055e477ae
commit b57f362e3a
3 changed files with 39 additions and 16 deletions

View File

@@ -64,17 +64,20 @@ export class JsonField<Required extends true | false = false, TypeOverride = obj
return false;
}
override isValid(value: any): boolean {
return this.isSerializable(value);
}
override getValue(value: any, context: TRenderContext): any {
switch (context) {
case "form":
if (value === null) return "";
return JSON.stringify(value, null, 2);
case "table":
if (value === null) return null;
return JSON.stringify(value);
case "submit":
if (typeof value === "string" && value.length === 0) {
if (!value || (typeof value === "string" && value.length === 0)) {
return null;
} else if (typeof value === "object") {
return value;
}
return JSON.parse(value);

View File

@@ -1,4 +1,4 @@
import { Suspense, lazy, useState } from "react";
import { Suspense, lazy, useEffect, useState } from "react";
import { twMerge } from "tailwind-merge";
import type { CodeEditorProps } from "./CodeEditor";
import { useDebouncedCallback } from "@mantine/hooks";
@@ -7,7 +7,8 @@ const CodeEditor = lazy(() => import("./CodeEditor"));
export type JsonEditorProps = Omit<CodeEditorProps, "value" | "onChange"> & {
value?: object;
onChange?: (value: object) => void;
emptyAs?: "null" | "undefined";
emptyAs?: any;
onInvalid?: (error: Error) => void;
};
export function JsonEditor({
@@ -16,29 +17,45 @@ export function JsonEditor({
value,
onChange,
onBlur,
emptyAs = "undefined",
emptyAs = undefined,
onInvalid,
...props
}: JsonEditorProps) {
const [editorValue, setEditorValue] = useState<string | null | undefined>(
JSON.stringify(value, null, 2),
value ? JSON.stringify(value, null, 2) : emptyAs,
);
const [error, setError] = useState<boolean>(false);
const handleChange = useDebouncedCallback((given: string) => {
const value = given === "" ? (emptyAs === "null" ? null : undefined) : given;
try {
setEditorValue(value);
onChange?.(value ? JSON.parse(value) : value);
} catch (e) {}
}, 500);
setError(false);
onChange?.(given ? JSON.parse(given) : emptyAs);
} catch (e) {
onInvalid?.(e as Error);
setError(true);
}
}, 250);
const handleBlur = (e) => {
setEditorValue(JSON.stringify(value, null, 2));
try {
const formatted = JSON.stringify(value, null, 2);
setEditorValue(formatted);
} catch (e) {}
onBlur?.(e);
};
useEffect(() => {
if (!editorValue) {
setEditorValue(value ? JSON.stringify(value, null, 2) : emptyAs);
}
}, [value]);
return (
<Suspense fallback={null}>
<CodeEditor
className={twMerge(
"flex w-full border border-muted",
!editable && "opacity-70",
error && "border-red-500",
className,
)}
editable={editable}

View File

@@ -3,7 +3,7 @@ import type { FieldApi, ReactFormExtendedApi } from "@tanstack/react-form";
import type { JSX } from "react";
import { useStore } from "@tanstack/react-store";
import { MediaField } from "media/MediaField";
import { type ComponentProps, Suspense } from "react";
import { type ComponentProps, Suspense, useState } from "react";
import { JsonEditor } from "ui/components/code/JsonEditor";
import * as Formy from "ui/components/form/Formy";
import { FieldLabel } from "ui/components/form/Formy";
@@ -287,12 +287,14 @@ function EntityJsonFormField({
field,
...props
}: { fieldApi: TFieldApi; field: JsonField }) {
const [error, setError] = useState<any>(null);
const handleUpdate = useEvent((value: any) => {
setError(null);
fieldApi.handleChange(value);
});
return (
<Formy.Group>
<Formy.Group error={!!error}>
<Formy.FieldLabel htmlFor={fieldApi.name} field={field} />
<Suspense>
<JsonEditor
@@ -300,6 +302,7 @@ function EntityJsonFormField({
value={fieldApi.state.value}
onChange={handleUpdate}
onBlur={fieldApi.handleBlur}
onInvalid={setError}
minHeight="100"
{...props}
/>