Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
F
frontend
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
vicotor
frontend
Commits
05e389dd
Commit
05e389dd
authored
Dec 08, 2023
by
tom
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
tuple type fields
parent
a8448fef
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
168 additions
and
85 deletions
+168
-85
contract.ts
types/api/contract.ts
+2
-1
ContractMethodCallable.tsx
ui/address/contract/ContractMethodCallable.tsx
+86
-70
ContractMethodCallableRow.tsx
ui/address/contract/ContractMethodCallableRow.tsx
+66
-0
ContractMethodField.tsx
ui/address/contract/ContractMethodField.tsx
+10
-10
ContractMethodFieldArray.tsx
ui/address/contract/ContractMethodFieldArray.tsx
+4
-4
No files found.
types/api/contract.ts
View file @
05e389dd
import
type
{
Abi
}
from
'
abitype
'
;
import
type
{
Abi
}
from
'
abitype
'
;
export
type
SmartContractMethodArgType
=
'
address
'
|
'
uint256
'
|
'
bool
'
|
'
string
'
|
'
bytes
'
|
'
bytes32
'
|
'
bytes32[]
'
;
export
type
SmartContractMethodArgType
=
'
address
'
|
'
uint256
'
|
'
bool
'
|
'
string
'
|
'
bytes
'
|
'
bytes32
'
|
'
bytes32[]
'
|
'
tuple
'
;
export
type
SmartContractMethodStateMutability
=
'
view
'
|
'
nonpayable
'
|
'
payable
'
;
export
type
SmartContractMethodStateMutability
=
'
view
'
|
'
nonpayable
'
|
'
payable
'
;
export
interface
SmartContract
{
export
interface
SmartContract
{
...
@@ -88,6 +88,7 @@ export interface SmartContractMethodInput {
...
@@ -88,6 +88,7 @@ export interface SmartContractMethodInput {
internalType
?:
SmartContractMethodArgType
;
internalType
?:
SmartContractMethodArgType
;
name
:
string
;
name
:
string
;
type
:
SmartContractMethodArgType
;
type
:
SmartContractMethodArgType
;
components
?:
Array
<
SmartContractMethodInput
>
;
}
}
export
interface
SmartContractMethodOutput
extends
SmartContractMethodInput
{
export
interface
SmartContractMethodOutput
extends
SmartContractMethodInput
{
...
...
ui/address/contract/ContractMethodCallable.tsx
View file @
05e389dd
import
{
Box
,
Button
,
chakra
,
Flex
,
Icon
,
Text
}
from
'
@chakra-ui/react
'
;
import
{
Box
,
Button
,
chakra
,
Flex
,
Icon
,
Text
}
from
'
@chakra-ui/react
'
;
import
_fromPairs
from
'
lodash/fromPairs
'
;
//
import _fromPairs from 'lodash/fromPairs';
import
React
from
'
react
'
;
import
React
from
'
react
'
;
import
type
{
SubmitHandler
}
from
'
react-hook-form
'
;
import
type
{
SubmitHandler
}
from
'
react-hook-form
'
;
import
{
useForm
}
from
'
react-hook-form
'
;
import
{
useForm
,
FormProvider
}
from
'
react-hook-form
'
;
import
type
{
MethodFormFields
,
ContractMethodCallResult
}
from
'
./types
'
;
import
type
{
MethodFormFields
,
ContractMethodCallResult
}
from
'
./types
'
;
import
type
{
SmartContractMethodInput
,
SmartContractMethod
,
SmartContractMethodArgType
}
from
'
types/api/contract
'
;
import
type
{
SmartContractMethodInput
,
SmartContractMethod
}
from
'
types/api/contract
'
;
import
arrowIcon
from
'
icons/arrows/down-right.svg
'
;
import
arrowIcon
from
'
icons/arrows/down-right.svg
'
;
import
*
as
mixpanel
from
'
lib/mixpanel/index
'
;
import
*
as
mixpanel
from
'
lib/mixpanel/index
'
;
import
ContractMethodField
from
'
./ContractMethodField
'
;
import
ContractMethodCallableRow
from
'
./ContractMethodCallableRow
'
;
import
ContractMethodFieldArray
from
'
./ContractMethodFieldArray
'
;
import
{
ARRAY_REGEXP
}
from
'
./utils
'
;
interface
ResultComponentProps
<
T
extends
SmartContractMethod
>
{
interface
ResultComponentProps
<
T
extends
SmartContractMethod
>
{
item
:
T
;
item
:
T
;
...
@@ -27,8 +25,11 @@ interface Props<T extends SmartContractMethod> {
...
@@ -27,8 +25,11 @@ interface Props<T extends SmartContractMethod> {
isWrite
?:
boolean
;
isWrite
?:
boolean
;
}
}
// TODO @tom2drum remove this
const
getFieldName
=
(
name
:
string
|
undefined
,
index
:
number
):
string
=>
name
||
String
(
index
);
const
getFieldName
=
(
name
:
string
|
undefined
,
index
:
number
):
string
=>
name
||
String
(
index
);
const
getFormFieldName
=
(
inputName
:
string
,
inputIndex
:
number
,
group
?:
string
)
=>
`
${
group
?
`
${
group
}
_`
:
''
}${
inputName
||
'
input
'
}
-
${
inputIndex
}
}`
;
const
sortFields
=
(
data
:
Array
<
SmartContractMethodInput
>
)
=>
(
const
sortFields
=
(
data
:
Array
<
SmartContractMethodInput
>
)
=>
(
[
a
]:
[
string
,
string
|
Array
<
string
>
],
[
a
]:
[
string
,
string
|
Array
<
string
>
],
[
b
]:
[
string
,
string
|
Array
<
string
>
],
[
b
]:
[
string
,
string
|
Array
<
string
>
],
...
@@ -87,8 +88,9 @@ const ContractMethodCallable = <T extends SmartContractMethod>({ data, onSubmit,
...
@@ -87,8 +88,9 @@ const ContractMethodCallable = <T extends SmartContractMethod>({ data, onSubmit,
];
];
},
[
data
]);
},
[
data
]);
const
{
control
,
handleSubmit
,
setValue
,
getValues
}
=
useForm
<
MethodFormFields
>
({
const
formApi
=
useForm
<
MethodFormFields
>
({
defaultValues
:
_fromPairs
(
inputs
.
map
(({
name
},
index
)
=>
[
getFieldName
(
name
,
index
),
''
])),
// TODO @tom2drum rewrite this
// defaultValues: _fromPairs(inputs.map((
{
name
},
index
)
=>
[
getFieldName
(
name
,
index
),
''
])),
mode
:
'
onBlur
'
,
mode
:
'
onBlur
'
,
});
});
...
@@ -101,6 +103,10 @@ const ContractMethodCallable = <T extends SmartContractMethod>({ data, onSubmit,
...
@@ -101,6 +103,10 @@ const ContractMethodCallable = <T extends SmartContractMethod>({ data, onSubmit,
},
[
result
]);
},
[
result
]);
const
onFormSubmit
:
SubmitHandler
<
MethodFormFields
>
=
React
.
useCallback
(
async
(
formData
)
=>
{
const
onFormSubmit
:
SubmitHandler
<
MethodFormFields
>
=
React
.
useCallback
(
async
(
formData
)
=>
{
// console.log('__>__ formData', formData);
// debugger;
const
args
=
Object
.
entries
(
formData
)
const
args
=
Object
.
entries
(
formData
)
.
sort
(
sortFields
(
inputs
))
.
sort
(
sortFields
(
inputs
))
.
map
(
castFieldValue
(
inputs
))
.
map
(
castFieldValue
(
inputs
))
...
@@ -127,69 +133,79 @@ const ContractMethodCallable = <T extends SmartContractMethod>({ data, onSubmit,
...
@@ -127,69 +133,79 @@ const ContractMethodCallable = <T extends SmartContractMethod>({ data, onSubmit,
return
(
return
(
<
Box
>
<
Box
>
<
chakra
.
form
<
FormProvider
{
...
formApi
}
>
noValidate
<
chakra
.
form
display=
"grid"
noValidate
columnGap=
{
3
}
display=
"grid"
rowGap=
{
{
base
:
2
,
lg
:
3
}
}
columnGap=
{
3
}
gridTemplateColumns=
{
{
base
:
'
minmax(0, 1fr)
'
,
lg
:
'
minmax(min-content, 180px) minmax(0, 1fr)
'
}
}
rowGap=
{
{
base
:
2
,
lg
:
3
}
}
onSubmit=
{
handleSubmit
(
onFormSubmit
)
}
gridTemplateColumns=
{
{
base
:
'
minmax(0, 1fr)
'
,
lg
:
'
minmax(min-content, 250px) minmax(0, 1fr)
'
}
}
onChange=
{
handleFormChange
}
onSubmit=
{
formApi
.
handleSubmit
(
onFormSubmit
)
}
>
onChange=
{
handleFormChange
}
{
inputs
.
map
(({
type
,
name
},
index
)
=>
{
const
fieldName
=
getFieldName
(
name
,
index
);
const
arrayTypeMatch
=
type
.
match
(
ARRAY_REGEXP
);
const
content
=
arrayTypeMatch
?
(
<
ContractMethodFieldArray
name=
{
fieldName
}
valueType=
{
arrayTypeMatch
[
1
]
as
SmartContractMethodArgType
}
size=
{
Number
(
arrayTypeMatch
[
2
]
||
Infinity
)
}
control=
{
control
}
setValue=
{
setValue
}
getValues=
{
getValues
}
isDisabled=
{
isLoading
}
onChange=
{
handleFormChange
}
/>
)
:
(
<
ContractMethodField
name=
{
fieldName
}
valueType=
{
type
}
placeholder=
{
`${ name }(${ type })`
}
control=
{
control
}
setValue=
{
setValue
}
getValues=
{
getValues
}
isDisabled=
{
isLoading
}
onChange=
{
handleFormChange
}
/>
);
return
(
<
React
.
Fragment
key=
{
index
}
>
<
Box
fontWeight=
{
500
}
lineHeight=
"20px"
py=
{
{
lg
:
'
6px
'
}
}
fontSize=
"sm"
>
{
name
}
(
{
type
}
)
</
Box
>
{
content
}
</
React
.
Fragment
>
);
})
}
<
Button
isLoading=
{
isLoading
}
loadingText=
{
isWrite
?
'
Write
'
:
'
Read
'
}
variant=
"outline"
size=
"sm"
flexShrink=
{
0
}
width=
"min-content"
px=
{
4
}
type=
"submit"
>
>
{
isWrite
?
'
Write
'
:
'
Read
'
}
{
inputs
.
map
((
input
,
index
)
=>
{
</
Button
>
const
fieldName
=
getFormFieldName
(
input
.
name
,
index
);
</
chakra
.
form
>
if
(
input
.
type
===
'
tuple
'
&&
input
.
components
)
{
return
(
<
React
.
Fragment
key=
{
fieldName
}
>
{
index
!==
0
&&
<><
Box
h=
{
{
base
:
0
,
lg
:
3
}
}
/><
div
/></>
}
<
Box
fontWeight=
{
500
}
lineHeight=
"20px"
py=
{
{
lg
:
'
6px
'
}
}
fontSize=
"sm"
wordBreak=
"break-word"
>
{
input
.
name
}
(
{
input
.
type
}
)
</
Box
>
<
div
/>
{
input
.
components
.
map
((
component
,
componentIndex
)
=>
{
const
fieldName
=
getFormFieldName
(
component
.
name
,
componentIndex
,
input
.
name
);
return
(
<
ContractMethodCallableRow
key=
{
fieldName
}
fieldName=
{
fieldName
}
argName=
{
component
.
name
}
argType=
{
component
.
type
}
isDisabled=
{
isLoading
}
onChange=
{
handleFormChange
}
isGrouped
/>
);
})
}
{
index
!==
inputs
.
length
-
1
&&
<><
Box
h=
{
{
base
:
0
,
lg
:
3
}
}
/><
div
/></>
}
</
React
.
Fragment
>
);
}
return
(
<
ContractMethodCallableRow
key=
{
fieldName
}
fieldName=
{
fieldName
}
argName=
{
input
.
name
}
argType=
{
input
.
type
}
isDisabled=
{
isLoading
}
onChange=
{
handleFormChange
}
/>
);
})
}
<
div
/>
<
Button
isLoading=
{
isLoading
}
loadingText=
{
isWrite
?
'
Write
'
:
'
Read
'
}
variant=
"outline"
size=
"sm"
flexShrink=
{
0
}
width=
"min-content"
px=
{
4
}
type=
"submit"
>
{
isWrite
?
'
Write
'
:
'
Read
'
}
</
Button
>
</
chakra
.
form
>
</
FormProvider
>
{
'
outputs
'
in
data
&&
!
isWrite
&&
data
.
outputs
.
length
>
0
&&
(
{
'
outputs
'
in
data
&&
!
isWrite
&&
data
.
outputs
.
length
>
0
&&
(
<
Flex
mt=
{
3
}
>
<
Flex
mt=
{
3
}
>
<
Icon
as=
{
arrowIcon
}
boxSize=
{
5
}
mr=
{
1
}
/>
<
Icon
as=
{
arrowIcon
}
boxSize=
{
5
}
mr=
{
1
}
/>
...
...
ui/address/contract/ContractMethodCallableRow.tsx
0 → 100644
View file @
05e389dd
import
{
Box
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
{
useFormContext
}
from
'
react-hook-form
'
;
import
type
{
MethodFormFields
}
from
'
./types
'
;
import
type
{
SmartContractMethodArgType
}
from
'
types/api/contract
'
;
import
ContractMethodField
from
'
./ContractMethodField
'
;
import
ContractMethodFieldArray
from
'
./ContractMethodFieldArray
'
;
import
{
ARRAY_REGEXP
}
from
'
./utils
'
;
interface
Props
{
fieldName
:
string
;
argName
:
string
;
argType
:
SmartContractMethodArgType
;
onChange
:
()
=>
void
;
isDisabled
:
boolean
;
isGrouped
?:
boolean
;
}
const
ContractMethodCallableRow
=
({
argName
,
fieldName
,
argType
,
onChange
,
isDisabled
,
isGrouped
}:
Props
)
=>
{
const
{
control
,
getValues
,
setValue
}
=
useFormContext
<
MethodFormFields
>
();
const
arrayTypeMatch
=
argType
.
match
(
ARRAY_REGEXP
);
const
content
=
arrayTypeMatch
?
(
<
ContractMethodFieldArray
name=
{
fieldName
}
argType=
{
arrayTypeMatch
[
1
]
as
SmartContractMethodArgType
}
size=
{
Number
(
arrayTypeMatch
[
2
]
||
Infinity
)
}
control=
{
control
}
setValue=
{
setValue
}
getValues=
{
getValues
}
isDisabled=
{
isDisabled
}
onChange=
{
onChange
}
/>
)
:
(
<
ContractMethodField
name=
{
fieldName
}
argType=
{
argType
}
placeholder=
{
argType
}
control=
{
control
}
setValue=
{
setValue
}
getValues=
{
getValues
}
isDisabled=
{
isDisabled
}
onChange=
{
onChange
}
/>
);
return
(
<>
<
Box
fontWeight=
{
500
}
lineHeight=
"20px"
py=
{
{
lg
:
'
6px
'
}
}
fontSize=
"sm"
color=
{
isGrouped
?
'
text_secondary
'
:
'
initial
'
}
wordBreak=
"break-word"
>
{
argName
}
(
{
argType
}
)
</
Box
>
{
content
}
</>
);
};
export
default
React
.
memo
(
ContractMethodCallableRow
);
ui/address/contract/ContractMethodField.tsx
View file @
05e389dd
...
@@ -25,7 +25,7 @@ interface Props {
...
@@ -25,7 +25,7 @@ interface Props {
index
?:
number
;
index
?:
number
;
groupName
?:
string
;
groupName
?:
string
;
placeholder
:
string
;
placeholder
:
string
;
value
Type
:
SmartContractMethodArgType
;
arg
Type
:
SmartContractMethodArgType
;
control
:
Control
<
MethodFormFields
>
;
control
:
Control
<
MethodFormFields
>
;
setValue
:
UseFormSetValue
<
MethodFormFields
>
;
setValue
:
UseFormSetValue
<
MethodFormFields
>
;
getValues
:
UseFormGetValues
<
MethodFormFields
>
;
getValues
:
UseFormGetValues
<
MethodFormFields
>
;
...
@@ -33,7 +33,7 @@ interface Props {
...
@@ -33,7 +33,7 @@ interface Props {
onChange
:
()
=>
void
;
onChange
:
()
=>
void
;
}
}
const
ContractMethodField
=
({
control
,
name
,
groupName
,
index
,
value
Type
,
placeholder
,
setValue
,
getValues
,
isDisabled
,
onChange
}:
Props
)
=>
{
const
ContractMethodField
=
({
control
,
name
,
groupName
,
index
,
arg
Type
,
placeholder
,
setValue
,
getValues
,
isDisabled
,
onChange
}:
Props
)
=>
{
const
ref
=
React
.
useRef
<
HTMLInputElement
>
(
null
);
const
ref
=
React
.
useRef
<
HTMLInputElement
>
(
null
);
const
handleClear
=
React
.
useCallback
(()
=>
{
const
handleClear
=
React
.
useCallback
(()
=>
{
...
@@ -51,7 +51,7 @@ const ContractMethodField = ({ control, name, groupName, index, valueType, place
...
@@ -51,7 +51,7 @@ const ContractMethodField = ({ control, name, groupName, index, valueType, place
},
[
getValues
,
groupName
,
index
,
name
,
onChange
,
setValue
]);
},
[
getValues
,
groupName
,
index
,
name
,
onChange
,
setValue
]);
const
intMatch
=
React
.
useMemo
(()
=>
{
const
intMatch
=
React
.
useMemo
(()
=>
{
const
match
=
value
Type
.
match
(
INT_REGEXP
);
const
match
=
arg
Type
.
match
(
INT_REGEXP
);
if
(
!
match
)
{
if
(
!
match
)
{
return
null
;
return
null
;
}
}
...
@@ -60,11 +60,11 @@ const ContractMethodField = ({ control, name, groupName, index, valueType, place
...
@@ -60,11 +60,11 @@ const ContractMethodField = ({ control, name, groupName, index, valueType, place
const
[
min
,
max
]
=
getIntBoundaries
(
Number
(
power
),
Boolean
(
isUnsigned
));
const
[
min
,
max
]
=
getIntBoundaries
(
Number
(
power
),
Boolean
(
isUnsigned
));
return
{
isUnsigned
,
power
,
min
,
max
};
return
{
isUnsigned
,
power
,
min
,
max
};
},
[
value
Type
]);
},
[
arg
Type
]);
const
bytesMatch
=
React
.
useMemo
(()
=>
{
const
bytesMatch
=
React
.
useMemo
(()
=>
{
return
value
Type
.
match
(
BYTES_REGEXP
);
return
arg
Type
.
match
(
BYTES_REGEXP
);
},
[
value
Type
]);
},
[
arg
Type
]);
const
renderInput
=
React
.
useCallback
((
const
renderInput
=
React
.
useCallback
((
{
field
,
formState
}:
{
field
:
ControllerRenderProps
<
MethodFormFields
>
;
formState
:
UseFormStateReturn
<
MethodFormFields
>
},
{
field
,
formState
}:
{
field
:
ControllerRenderProps
<
MethodFormFields
>
;
formState
:
UseFormStateReturn
<
MethodFormFields
>
},
...
@@ -111,11 +111,11 @@ const ContractMethodField = ({ control, name, groupName, index, valueType, place
...
@@ -111,11 +111,11 @@ const ContractMethodField = ({ control, name, groupName, index, valueType, place
},
[
index
,
groupName
,
name
,
intMatch
,
isDisabled
,
placeholder
,
handleClear
,
handleAddZeroesClick
]);
},
[
index
,
groupName
,
name
,
intMatch
,
isDisabled
,
placeholder
,
handleClear
,
handleAddZeroesClick
]);
const
validate
=
React
.
useCallback
((
value
:
string
|
Array
<
string
>
)
=>
{
const
validate
=
React
.
useCallback
((
value
:
string
|
Array
<
string
>
)
=>
{
if
(
typeof
value
===
'
object
'
)
{
if
(
typeof
value
===
'
object
'
||
!
value
)
{
return
;
return
;
}
}
if
(
value
Type
===
'
address
'
)
{
if
(
arg
Type
===
'
address
'
)
{
return
!
isAddress
(
value
)
?
'
Invalid address format
'
:
true
;
return
!
isAddress
(
value
)
?
'
Invalid address format
'
:
true
;
}
}
...
@@ -135,7 +135,7 @@ const ContractMethodField = ({ control, name, groupName, index, valueType, place
...
@@ -135,7 +135,7 @@ const ContractMethodField = ({ control, name, groupName, index, valueType, place
return
true
;
return
true
;
}
}
if
(
value
Type
===
'
bool
'
)
{
if
(
arg
Type
===
'
bool
'
)
{
const
formattedValue
=
formatBooleanValue
(
value
);
const
formattedValue
=
formatBooleanValue
(
value
);
if
(
formattedValue
===
undefined
)
{
if
(
formattedValue
===
undefined
)
{
return
'
Invalid boolean format. Allowed values: 0, 1, true, false
'
;
return
'
Invalid boolean format. Allowed values: 0, 1, true, false
'
;
...
@@ -160,7 +160,7 @@ const ContractMethodField = ({ control, name, groupName, index, valueType, place
...
@@ -160,7 +160,7 @@ const ContractMethodField = ({ control, name, groupName, index, valueType, place
}
}
return
true
;
return
true
;
},
[
bytesMatch
,
intMatch
,
value
Type
]);
},
[
bytesMatch
,
intMatch
,
arg
Type
]);
return
(
return
(
<
Controller
<
Controller
...
...
ui/address/contract/ContractMethodFieldArray.tsx
View file @
05e389dd
...
@@ -14,7 +14,7 @@ import ContractMethodField from './ContractMethodField';
...
@@ -14,7 +14,7 @@ import ContractMethodField from './ContractMethodField';
interface
Props
{
interface
Props
{
name
:
string
;
name
:
string
;
size
:
number
;
size
:
number
;
value
Type
:
SmartContractMethodArgType
;
arg
Type
:
SmartContractMethodArgType
;
control
:
Control
<
MethodFormFields
>
;
control
:
Control
<
MethodFormFields
>
;
setValue
:
UseFormSetValue
<
MethodFormFields
>
;
setValue
:
UseFormSetValue
<
MethodFormFields
>
;
getValues
:
UseFormGetValues
<
MethodFormFields
>
;
getValues
:
UseFormGetValues
<
MethodFormFields
>
;
...
@@ -22,7 +22,7 @@ interface Props {
...
@@ -22,7 +22,7 @@ interface Props {
onChange
:
()
=>
void
;
onChange
:
()
=>
void
;
}
}
const
ContractMethodFieldArray
=
({
control
,
name
,
setValue
,
getValues
,
isDisabled
,
value
Type
,
onChange
}:
Props
)
=>
{
const
ContractMethodFieldArray
=
({
control
,
name
,
setValue
,
getValues
,
isDisabled
,
arg
Type
,
onChange
}:
Props
)
=>
{
const
{
fields
,
append
,
remove
}
=
useFieldArray
({
const
{
fields
,
append
,
remove
}
=
useFieldArray
({
name
:
name
as
never
,
name
:
name
as
never
,
control
,
control
,
...
@@ -52,8 +52,8 @@ const ContractMethodFieldArray = ({ control, name, setValue, getValues, isDisabl
...
@@ -52,8 +52,8 @@ const ContractMethodFieldArray = ({ control, name, setValue, getValues, isDisabl
name=
{
`${ name }[${ index }]`
}
name=
{
`${ name }[${ index }]`
}
groupName=
{
name
}
groupName=
{
name
}
index=
{
index
}
index=
{
index
}
valueType=
{
value
Type
}
argType=
{
arg
Type
}
placeholder=
{
value
Type
}
placeholder=
{
arg
Type
}
control=
{
control
}
control=
{
control
}
setValue=
{
setValue
}
setValue=
{
setValue
}
getValues=
{
getValues
}
getValues=
{
getValues
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment