mirror of
https://github.com/smartxworks/sunmao-ui.git
synced 2024-11-21 03:15:49 +08:00
add dialog form
This commit is contained in:
parent
288a432923
commit
8eaec48b97
563
packages/runtime/example/form/dialogForm.html
Normal file
563
packages/runtime/example/form/dialogForm.html
Normal file
@ -0,0 +1,563 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>meta-ui runtime example: input validation component</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module">
|
||||
import renderApp from '../../src/main.tsx';
|
||||
|
||||
renderApp({
|
||||
version: 'example/v1',
|
||||
metadata: {
|
||||
name: 'dialog form',
|
||||
description: 'dialog form example',
|
||||
},
|
||||
spec: {
|
||||
components: [
|
||||
{
|
||||
id: 'fetchVolumes',
|
||||
type: 'core/v1/dummy',
|
||||
properties: {},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/fetch',
|
||||
properties: {
|
||||
name: 'query',
|
||||
url: 'https://61373521eac1410017c18209.mockapi.io/Volume',
|
||||
method: 'get',
|
||||
lazy: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'createVolume',
|
||||
type: 'core/v1/dummy',
|
||||
properties: {},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/fetch',
|
||||
properties: {
|
||||
url: 'https://61373521eac1410017c18209.mockapi.io/Volume',
|
||||
method: 'post',
|
||||
lazy: true,
|
||||
headers: [
|
||||
{ key: 'Content-Type', value: 'application/json' },
|
||||
],
|
||||
body: '{{ form.data }}',
|
||||
onComplete: [
|
||||
{
|
||||
componentId: '$utils',
|
||||
method: {
|
||||
name: 'toast.open',
|
||||
parameters: {
|
||||
id: 'createSuccessToast',
|
||||
title: '太棒了',
|
||||
description: '创建虚拟卷成功了',
|
||||
position: 'bottom-right',
|
||||
duration: null,
|
||||
isClosable: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
componentId: 'editDialog',
|
||||
method: {
|
||||
name: 'cancelDialog',
|
||||
},
|
||||
},
|
||||
{
|
||||
componentId: 'form',
|
||||
method: {
|
||||
name: 'resetForm',
|
||||
},
|
||||
},
|
||||
{
|
||||
componentId: 'fetchVolumes',
|
||||
method: {
|
||||
name: 'triggerFetch',
|
||||
parameters: 'query',
|
||||
},
|
||||
wait: {},
|
||||
disabled: 'false',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'deleteVolume',
|
||||
type: 'core/v1/dummy',
|
||||
properties: {},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/fetch',
|
||||
properties: {
|
||||
url: 'https://61373521eac1410017c18209.mockapi.io/Volume/{{ table.selectedItem ? table.selectedItem.id : "" }}',
|
||||
method: 'delete',
|
||||
lazy: true,
|
||||
onComplete: [
|
||||
{
|
||||
componentId: 'fetchVolumes',
|
||||
method: {
|
||||
name: 'triggerFetch',
|
||||
parameters: 'query',
|
||||
},
|
||||
wait: {},
|
||||
disabled: 'false',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'root',
|
||||
type: 'chakra_ui/v1/root',
|
||||
properties: {},
|
||||
traits: [],
|
||||
},
|
||||
{
|
||||
id: 'editDialog',
|
||||
type: 'chakra_ui/v1/dialog',
|
||||
properties: {
|
||||
title: 'This is a dialog',
|
||||
confirmButton: {
|
||||
text: '保存',
|
||||
colorScheme: 'purple',
|
||||
},
|
||||
cancelButton: {
|
||||
text: '取消',
|
||||
},
|
||||
disableConfirm: '{{ form.disableSubmit }}',
|
||||
},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: {
|
||||
container: {
|
||||
id: 'root',
|
||||
slot: 'root',
|
||||
},
|
||||
},
|
||||
},
|
||||
// dialog events
|
||||
{
|
||||
type: 'core/v1/event',
|
||||
parsedType: {
|
||||
version: 'core/v1',
|
||||
name: 'event',
|
||||
},
|
||||
properties: {
|
||||
events: [
|
||||
// when click confirm
|
||||
{
|
||||
event: 'confirmDialog',
|
||||
componentId: 'createVolume',
|
||||
method: {
|
||||
name: 'triggerFetch',
|
||||
},
|
||||
wait: {},
|
||||
disabled: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'table',
|
||||
type: 'chakra_ui/v1/table',
|
||||
properties: {
|
||||
data: '{{ fetchVolumes.fetch.data }}',
|
||||
majorKey: 'id',
|
||||
rowsPerPage: 5,
|
||||
columns: [
|
||||
{
|
||||
key: 'id',
|
||||
title: 'ID',
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
key: 'name',
|
||||
title: '名称',
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
key: 'type',
|
||||
title: '类别',
|
||||
type: 'text',
|
||||
displayValue:
|
||||
'{{$listItem.type === "sharing" ? "共享虚拟卷" : "虚拟卷"}}',
|
||||
},
|
||||
{
|
||||
key: 'size',
|
||||
title: '容量',
|
||||
type: 'text',
|
||||
displayValue: '{{$listItem.size}} GiB',
|
||||
},
|
||||
{
|
||||
key: 'policy',
|
||||
title: '存储策略',
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
key: 'isActive',
|
||||
title: '是否激活',
|
||||
type: 'text',
|
||||
displayValue: '{{$listItem.isActive ? "是" : "否"}}',
|
||||
},
|
||||
{
|
||||
key: 'operation',
|
||||
title: '操作',
|
||||
type: 'button',
|
||||
buttonConfig: {
|
||||
text: '删除',
|
||||
events: [
|
||||
{
|
||||
componentId: 'deleteVolume',
|
||||
method: {
|
||||
name: 'triggerFetch',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'edit',
|
||||
title: '创建',
|
||||
type: 'button',
|
||||
buttonConfig: {
|
||||
text: '创建',
|
||||
events: [
|
||||
{
|
||||
componentId: 'editDialog',
|
||||
method: {
|
||||
name: 'openDialog',
|
||||
parameters: {
|
||||
title: '创建虚拟卷',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: {
|
||||
container: {
|
||||
id: 'root',
|
||||
slot: 'root',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'form',
|
||||
type: 'chakra_ui/v1/form',
|
||||
properties: {
|
||||
hideSubmit: true,
|
||||
},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: {
|
||||
container: {
|
||||
id: 'editDialog',
|
||||
slot: 'content',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'nameFormControl',
|
||||
type: 'chakra_ui/v1/formControl',
|
||||
properties: {
|
||||
label: '名称',
|
||||
fieldName: 'name',
|
||||
isRequired: true,
|
||||
},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: {
|
||||
container: {
|
||||
id: 'form',
|
||||
slot: 'content',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'nameInput',
|
||||
type: 'chakra_ui/v1/input',
|
||||
properties: {
|
||||
defaultValue:
|
||||
'{{ table.selectedItem ? table.selectedItem.name : "" }}',
|
||||
},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: {
|
||||
container: {
|
||||
id: 'nameFormControl',
|
||||
slot: 'content',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'core/v1/validation',
|
||||
properties: {
|
||||
value: '{{ nameInput.value || "" }}',
|
||||
maxLength: 10,
|
||||
minLength: 2,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'typeFormControl',
|
||||
type: 'chakra_ui/v1/formControl',
|
||||
properties: {
|
||||
label: '类型',
|
||||
fieldName: 'type',
|
||||
helperText:
|
||||
'共享虚拟卷支持被多台虚拟机同时挂载。类型创建后不可修改。',
|
||||
},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: {
|
||||
container: {
|
||||
id: 'form',
|
||||
slot: 'content',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'typeRadioGroup',
|
||||
type: 'chakra_ui/v1/radio_group',
|
||||
properties: {
|
||||
defaultValue:
|
||||
'{{ table.selectedItem ? table.selectedItem.type : "notSharing" }}',
|
||||
},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: {
|
||||
container: {
|
||||
id: 'typeFormControl',
|
||||
slot: 'content',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'radio1',
|
||||
type: 'chakra_ui/v1/radio',
|
||||
properties: {
|
||||
text: {
|
||||
raw: '虚拟卷',
|
||||
format: 'plain',
|
||||
},
|
||||
value: 'notSharing',
|
||||
},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: {
|
||||
container: {
|
||||
id: 'typeRadioGroup',
|
||||
slot: 'content',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'radio2',
|
||||
type: 'chakra_ui/v1/radio',
|
||||
properties: {
|
||||
text: {
|
||||
raw: '共享虚拟卷',
|
||||
format: 'plain',
|
||||
},
|
||||
value: 'sharing',
|
||||
size: 'md',
|
||||
},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: {
|
||||
container: {
|
||||
id: 'typeRadioGroup',
|
||||
slot: 'content',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'sizeFormControl',
|
||||
type: 'chakra_ui/v1/formControl',
|
||||
properties: {
|
||||
label: '容量',
|
||||
fieldName: 'size',
|
||||
isRequired: true,
|
||||
},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: {
|
||||
container: {
|
||||
id: 'form',
|
||||
slot: 'content',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'sizeInput',
|
||||
type: 'chakra_ui/v1/number_input',
|
||||
properties: {
|
||||
defaultValue:
|
||||
'{{ table.selectedItem ? table.selectedItem.size : 0 }}',
|
||||
min: 0,
|
||||
max: 100,
|
||||
step: 5,
|
||||
precision: 2,
|
||||
clampValueOnBlur: false,
|
||||
allowMouseWheel: true,
|
||||
},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: {
|
||||
container: {
|
||||
id: 'sizeFormControl',
|
||||
slot: 'content',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'policyFormControl',
|
||||
type: 'chakra_ui/v1/formControl',
|
||||
properties: {
|
||||
label: '存储策略',
|
||||
fieldName: 'policy',
|
||||
},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: {
|
||||
container: {
|
||||
id: 'form',
|
||||
slot: 'content',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'policySelect',
|
||||
type: 'chakra_ui/v1/select',
|
||||
properties: {
|
||||
defaultValue:
|
||||
'{{ table.selectedItem ? table.selectedItem.policy : "2thin" }}',
|
||||
options: [
|
||||
{
|
||||
value: '2thin',
|
||||
label: '2 副本,精简置备',
|
||||
},
|
||||
{
|
||||
value: '3thin',
|
||||
label: '3 副本,精简置备',
|
||||
},
|
||||
{
|
||||
value: '2thick',
|
||||
label: '2 副本,厚置备',
|
||||
},
|
||||
{
|
||||
value: '3thick',
|
||||
label: '3 副本,厚置备',
|
||||
},
|
||||
],
|
||||
},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: {
|
||||
container: {
|
||||
id: 'policyFormControl',
|
||||
slot: 'content',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'isActiveFormControl',
|
||||
type: 'chakra_ui/v1/formControl',
|
||||
properties: {
|
||||
label: '激活',
|
||||
fieldName: 'isActive',
|
||||
},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: {
|
||||
container: {
|
||||
id: 'form',
|
||||
slot: 'content',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'checkbox',
|
||||
type: 'chakra_ui/v1/checkbox',
|
||||
properties: {
|
||||
value: 'isActive',
|
||||
defaultIsChecked:
|
||||
'{{table.selectedItem ? !!table.selectedItem.isActive : false}}',
|
||||
text: {
|
||||
raw: '激活',
|
||||
format: 'plain',
|
||||
},
|
||||
},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: {
|
||||
container: {
|
||||
id: 'isActiveFormControl',
|
||||
slot: 'content',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -13,8 +13,8 @@
|
||||
renderApp({
|
||||
version: 'example/v1',
|
||||
metadata: {
|
||||
name: 'api form',
|
||||
description: 'api form example',
|
||||
name: 'table form',
|
||||
description: 'table form example',
|
||||
},
|
||||
spec: {
|
||||
components: [
|
@ -15,6 +15,7 @@ import Slot from '../_internal/Slot';
|
||||
import { ColorSchemePropertySchema } from './Types/ColorScheme';
|
||||
|
||||
const TitlePropertySchema = Type.Optional(Type.String());
|
||||
const DisableConfirmPropertySchema = Type.Optional(Type.Boolean());
|
||||
|
||||
const HandleButtonPropertySchema = Type.Object({
|
||||
text: Type.Optional(Type.String()),
|
||||
@ -25,11 +26,13 @@ const Dialog: ComponentImplementation<{
|
||||
title?: Static<typeof TitlePropertySchema>;
|
||||
confirmButton?: Static<typeof HandleButtonPropertySchema>;
|
||||
cancelButton?: Static<typeof HandleButtonPropertySchema>;
|
||||
disableConfirm?: Static<typeof DisableConfirmPropertySchema>;
|
||||
}> = ({
|
||||
slotsMap,
|
||||
subscribeMethods,
|
||||
callbackMap: callbacks,
|
||||
title: customerTitle,
|
||||
disableConfirm,
|
||||
confirmButton = {
|
||||
text: 'confirm',
|
||||
colorScheme: 'red',
|
||||
@ -80,6 +83,7 @@ const Dialog: ComponentImplementation<{
|
||||
{cancelButton.text}
|
||||
</Button>
|
||||
<Button
|
||||
disabled={disableConfirm}
|
||||
colorScheme={confirmButton.colorScheme}
|
||||
onClick={callbacks?.confirmDialog}
|
||||
ml={3}>
|
||||
@ -114,6 +118,10 @@ export default {
|
||||
name: 'cancelButton',
|
||||
...HandleButtonPropertySchema,
|
||||
},
|
||||
{
|
||||
name: 'disableConfirm',
|
||||
...DisableConfirmPropertySchema,
|
||||
},
|
||||
],
|
||||
acceptTraits: [],
|
||||
state: {},
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { Type } from '@sinclair/typebox';
|
||||
import { createComponent } from '@meta-ui/core';
|
||||
import { ComponentImplementation } from '../../registry';
|
||||
import Slot from '../_internal/Slot';
|
||||
@ -7,14 +7,10 @@ import { Button } from '@chakra-ui/react';
|
||||
import { stateStore } from '../../store';
|
||||
import { watch } from '@vue-reactivity/watch';
|
||||
import { apiService } from '../../api-service';
|
||||
import { CheckboxStateSchema } from './Checkbox';
|
||||
|
||||
const FormImpl: ComponentImplementation<Record<string, string>> = ({
|
||||
mergeState,
|
||||
subscribeMethods,
|
||||
slotsMap,
|
||||
callbackMap,
|
||||
}) => {
|
||||
const FormImpl: ComponentImplementation<{
|
||||
hideSubmit?: boolean;
|
||||
}> = ({ mergeState, subscribeMethods, hideSubmit, slotsMap, callbackMap }) => {
|
||||
// 理论上说slotsMap是永远不变的
|
||||
const formControlIds = useMemo<string[]>(() => {
|
||||
return (
|
||||
@ -25,6 +21,8 @@ const FormImpl: ComponentImplementation<Record<string, string>> = ({
|
||||
}, [slotsMap]);
|
||||
|
||||
const [invalidArray, setInvalidArray] = useState<boolean[]>([]);
|
||||
const [disableSubmit, setDisableSubmit] = useState<boolean>(false);
|
||||
const dataRef = useRef<Record<string, any>>({});
|
||||
|
||||
useEffect(() => {
|
||||
setInvalidArray(
|
||||
@ -34,6 +32,14 @@ const FormImpl: ComponentImplementation<Record<string, string>> = ({
|
||||
);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const disable = invalidArray.some(v => v);
|
||||
setDisableSubmit(disable);
|
||||
mergeState({
|
||||
disableSubmit: disable,
|
||||
});
|
||||
}, [invalidArray]);
|
||||
|
||||
useEffect(() => {
|
||||
subscribeMethods({
|
||||
resetForm() {
|
||||
@ -51,7 +57,8 @@ const FormImpl: ComponentImplementation<Record<string, string>> = ({
|
||||
useEffect(() => {
|
||||
const stops: ReturnType<typeof watch>[] = [];
|
||||
formControlIds.forEach((fcId, i) => {
|
||||
const stop = watch(
|
||||
// watch isInvalid
|
||||
let stop = watch(
|
||||
() => {
|
||||
return stateStore[fcId].isInvalid;
|
||||
},
|
||||
@ -64,6 +71,19 @@ const FormImpl: ComponentImplementation<Record<string, string>> = ({
|
||||
}
|
||||
);
|
||||
stops.push(stop);
|
||||
|
||||
// watch value
|
||||
stop = watch(
|
||||
() => {
|
||||
return stateStore[fcId].value;
|
||||
},
|
||||
newV => {
|
||||
const fcState = stateStore[fcId];
|
||||
dataRef.current[fcState.fieldName] = newV;
|
||||
mergeState({ data: { ...dataRef.current } });
|
||||
}
|
||||
);
|
||||
stops.push(stop);
|
||||
});
|
||||
|
||||
return () => {
|
||||
@ -71,34 +91,20 @@ const FormImpl: ComponentImplementation<Record<string, string>> = ({
|
||||
s();
|
||||
});
|
||||
};
|
||||
}, []);
|
||||
}, [formControlIds]);
|
||||
|
||||
const onSubmit = () => {
|
||||
const data: Record<string, string | boolean> = {};
|
||||
formControlIds.forEach(fcId => {
|
||||
const fcState = stateStore[fcId];
|
||||
const fieldName = fcState.fieldName;
|
||||
if (stateStore[fcState.inputId].checked !== undefined) {
|
||||
// special treatment for checkbox
|
||||
data[fieldName] = (
|
||||
stateStore[fcState.inputId] as Static<typeof CheckboxStateSchema>
|
||||
).checked;
|
||||
} else {
|
||||
data[fieldName] = stateStore[fcState.inputId].value;
|
||||
}
|
||||
});
|
||||
mergeState({
|
||||
data,
|
||||
});
|
||||
callbackMap?.onSubmit();
|
||||
};
|
||||
|
||||
return (
|
||||
<form>
|
||||
<Slot slotsMap={slotsMap} slot="content" />
|
||||
<Button disabled={invalidArray.some(v => v)} onClick={onSubmit}>
|
||||
提交
|
||||
</Button>
|
||||
{hideSubmit ? undefined : (
|
||||
<Button disabled={disableSubmit} onClick={onSubmit}>
|
||||
提交
|
||||
</Button>
|
||||
)}
|
||||
</form>
|
||||
);
|
||||
};
|
||||
@ -111,10 +117,16 @@ export default {
|
||||
description: 'chakra-ui form',
|
||||
},
|
||||
spec: {
|
||||
properties: [],
|
||||
properties: [
|
||||
{
|
||||
name: 'hideSubmit',
|
||||
...Type.Boolean(),
|
||||
},
|
||||
],
|
||||
acceptTraits: [],
|
||||
state: Type.Object({
|
||||
data: Type.Any(),
|
||||
disableSubmit: Type.Boolean(),
|
||||
}),
|
||||
methods: [
|
||||
{
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import _ from 'lodash';
|
||||
import { createComponent } from '@meta-ui/core';
|
||||
import { Type } from '@sinclair/typebox';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
import {
|
||||
FormControl,
|
||||
FormErrorMessage,
|
||||
@ -12,6 +12,7 @@ import { ComponentImplementation } from '../../registry';
|
||||
import Slot from '../_internal/Slot';
|
||||
import { watch } from '@vue-reactivity/watch';
|
||||
import { stateStore } from '../../store';
|
||||
import { CheckboxStateSchema } from './Checkbox';
|
||||
|
||||
const FormControlImpl: ComponentImplementation<{
|
||||
label: string;
|
||||
@ -30,14 +31,22 @@ const FormControlImpl: ComponentImplementation<{
|
||||
|
||||
useEffect(() => {
|
||||
const inputId = _.first(slotsMap?.get('content'))?.id || '';
|
||||
return watch(
|
||||
const stop = watch(
|
||||
() => {
|
||||
return stateStore[inputId].value;
|
||||
if (stateStore[inputId].checked !== undefined) {
|
||||
// special treatment for checkbox
|
||||
return (stateStore[inputId] as Static<typeof CheckboxStateSchema>)
|
||||
.checked;
|
||||
} else {
|
||||
return stateStore[inputId].value;
|
||||
}
|
||||
},
|
||||
newV => {
|
||||
setInputValue(newV);
|
||||
}
|
||||
);
|
||||
setInputValue(stateStore[inputId].value);
|
||||
return stop;
|
||||
}, [slotsMap, setInputValue]);
|
||||
|
||||
useEffect(() => {
|
||||
@ -61,6 +70,7 @@ const FormControlImpl: ComponentImplementation<{
|
||||
inputId: _.first(slotsMap?.get('content'))?.id || '',
|
||||
fieldName,
|
||||
isInvalid: !!(isInvalid || (!inputValue && isRequired)),
|
||||
value: inputValue,
|
||||
});
|
||||
}, [slotsMap, fieldName, isInvalid, isRequired, inputValue]);
|
||||
|
||||
@ -107,6 +117,7 @@ export default {
|
||||
inputId: Type.String(),
|
||||
fieldName: Type.String(),
|
||||
isInvalid: Type.Boolean(),
|
||||
value: Type.Any(),
|
||||
}),
|
||||
methods: [],
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user