mirror of
https://github.com/IT4Change/ohmyform-ui.git
synced 2026-01-20 19:31:17 +00:00
add slider field type
This commit is contained in:
parent
94f1de3e25
commit
de1180d547
@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
- add default page background
|
||||
- add environment list in [doc](doc/environment.md)
|
||||
- show error message on homepage in case there is a problem with api connection
|
||||
- new slider field type
|
||||
|
||||
### Changed
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@ import { LinkType } from './link.type'
|
||||
import { NumberType } from './number.type'
|
||||
import { RadioType } from './radio.type'
|
||||
import { RatingType } from './rating.type'
|
||||
import { SliderType } from './slider.type'
|
||||
import { TextType } from './text.type'
|
||||
import { TextareaType } from './textarea.type'
|
||||
import { AdminFieldTypeProps } from './type.props'
|
||||
@ -15,15 +16,16 @@ import { YesNoType } from './yes_no.type'
|
||||
export const adminTypes: {
|
||||
[key: string]: React.FC<AdminFieldTypeProps>
|
||||
} = {
|
||||
textfield: TextType,
|
||||
date: DateType,
|
||||
email: EmailType,
|
||||
textarea: TextareaType,
|
||||
link: LinkType,
|
||||
dropdown: DropdownType,
|
||||
rating: RatingType,
|
||||
radio: RadioType,
|
||||
email: EmailType,
|
||||
hidden: HiddenType,
|
||||
yes_no: YesNoType,
|
||||
link: LinkType,
|
||||
number: NumberType,
|
||||
radio: RadioType,
|
||||
rating: RatingType,
|
||||
slider: SliderType,
|
||||
textarea: TextareaType,
|
||||
textfield: TextType,
|
||||
yes_no: YesNoType,
|
||||
}
|
||||
|
||||
90
components/form/admin/types/slider.type.tsx
Normal file
90
components/form/admin/types/slider.type.tsx
Normal file
@ -0,0 +1,90 @@
|
||||
import { Form, InputNumber, Slider } from 'antd'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { AdminFieldTypeProps } from './type.props'
|
||||
|
||||
export const SliderType: React.FC<AdminFieldTypeProps> = (props) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Form.Item shouldUpdate noStyle>
|
||||
{(form) => {
|
||||
const getValue = (name, defaultValue: number): number => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
const current = form.getFieldValue([
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
...form['prefixName'],
|
||||
props.field.name as string,
|
||||
'optionKeys',
|
||||
name,
|
||||
])
|
||||
|
||||
if (!current) {
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
return parseFloat(current)
|
||||
}
|
||||
|
||||
const max = getValue('max', 100)
|
||||
const min = getValue('min', 0)
|
||||
const step = getValue('step', 1)
|
||||
|
||||
return (
|
||||
<Form.Item
|
||||
label={t('type:slider.default')}
|
||||
name={[props.field.name as string, 'value']}
|
||||
labelCol={{ span: 6 }}
|
||||
getValueFromEvent={(value: number) =>
|
||||
typeof value === 'number' ? value.toFixed(2) : value
|
||||
}
|
||||
getValueProps={(value: string) => ({ value: value ? parseFloat(value) : undefined })}
|
||||
>
|
||||
<Slider min={min} max={max} step={step} dots={(max - min) / step <= 10} />
|
||||
</Form.Item>
|
||||
)
|
||||
}}
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label={t('type:slider.min')}
|
||||
name={[props.field.name as string, 'optionKeys', 'min']}
|
||||
labelCol={{ span: 6 }}
|
||||
initialValue={0}
|
||||
getValueFromEvent={(value: number) =>
|
||||
typeof value === 'number' ? value.toFixed(2) : value
|
||||
}
|
||||
getValueProps={(e: string) => ({ value: e ? parseFloat(e) : undefined })}
|
||||
>
|
||||
<InputNumber />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label={t('type:slider.max')}
|
||||
name={[props.field.name as string, 'optionKeys', 'max']}
|
||||
labelCol={{ span: 6 }}
|
||||
initialValue={100}
|
||||
getValueFromEvent={(value: number) =>
|
||||
typeof value === 'number' ? value.toFixed(2) : value
|
||||
}
|
||||
getValueProps={(e: string) => ({ value: e ? parseFloat(e) : undefined })}
|
||||
>
|
||||
<InputNumber />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label={t('type:slider.step')}
|
||||
name={[props.field.name as string, 'optionKeys', 'step']}
|
||||
labelCol={{ span: 6 }}
|
||||
initialValue={1}
|
||||
getValueFromEvent={(value: number) =>
|
||||
typeof value === 'number' ? value.toFixed(2) : value
|
||||
}
|
||||
getValueProps={(e: string) => ({ value: e ? parseFloat(e) : undefined })}
|
||||
>
|
||||
<InputNumber />
|
||||
</Form.Item>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@ -6,6 +6,7 @@ import { LinkType } from './link.type'
|
||||
import { NumberType } from './number.type'
|
||||
import { RadioType } from './radio.type'
|
||||
import { RatingType } from './rating.type'
|
||||
import { SliderType } from './slider.type'
|
||||
import { TextType } from './text.type'
|
||||
import { TextareaType } from './textarea.type'
|
||||
import { FieldTypeProps } from './type.props'
|
||||
@ -14,14 +15,15 @@ import { YesNoType } from './yes_no.type'
|
||||
export const fieldTypes: {
|
||||
[key: string]: React.FC<FieldTypeProps>
|
||||
} = {
|
||||
textfield: TextType,
|
||||
date: DateType,
|
||||
email: EmailType,
|
||||
textarea: TextareaType,
|
||||
link: LinkType,
|
||||
dropdown: DropdownType,
|
||||
rating: RatingType,
|
||||
radio: RadioType,
|
||||
yes_no: YesNoType,
|
||||
email: EmailType,
|
||||
link: LinkType,
|
||||
number: NumberType,
|
||||
radio: RadioType,
|
||||
rating: RatingType,
|
||||
slider: SliderType,
|
||||
textarea: TextareaType,
|
||||
textfield: TextType,
|
||||
yes_no: YesNoType,
|
||||
}
|
||||
|
||||
69
components/form/types/slider.type.tsx
Normal file
69
components/form/types/slider.type.tsx
Normal file
@ -0,0 +1,69 @@
|
||||
import { Form, Slider, Spin } from 'antd'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { FieldTypeProps } from './type.props'
|
||||
|
||||
export const SliderType: React.FC<FieldTypeProps> = ({ field, urlValue }) => {
|
||||
const [min, setMin] = useState<number>()
|
||||
const [max, setMax] = useState<number>()
|
||||
const [step, setStep] = useState<number>()
|
||||
const [loading, setLoading] = useState(true)
|
||||
|
||||
const { t } = useTranslation()
|
||||
|
||||
useEffect(() => {
|
||||
field.options.forEach((option) => {
|
||||
if (option.key === 'min') {
|
||||
setMin(parseFloat(option.value))
|
||||
}
|
||||
if (option.key === 'max') {
|
||||
setMax(parseFloat(option.value))
|
||||
}
|
||||
if (option.key === 'step') {
|
||||
setStep(parseFloat(option.value))
|
||||
}
|
||||
})
|
||||
|
||||
setLoading(false)
|
||||
}, [field])
|
||||
|
||||
let initialValue: number = undefined
|
||||
|
||||
if (field.value) {
|
||||
initialValue = parseFloat(field.value)
|
||||
}
|
||||
|
||||
if (urlValue) {
|
||||
initialValue = parseFloat(urlValue)
|
||||
}
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div>
|
||||
<Spin />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Form.Item
|
||||
name={[field.id, 'value']}
|
||||
rules={[{ required: field.required, message: t('validation:valueRequired') }]}
|
||||
initialValue={initialValue}
|
||||
getValueFromEvent={(value: number) =>
|
||||
typeof value === 'number' ? value.toFixed(2) : value
|
||||
}
|
||||
getValueProps={(value: string) => ({ value: value ? parseFloat(value) : undefined })}
|
||||
>
|
||||
<Slider
|
||||
min={min}
|
||||
max={max}
|
||||
step={step}
|
||||
tooltipVisible={true}
|
||||
dots={(max - min) / step <= 10}
|
||||
/>
|
||||
</Form.Item>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@ -19,6 +19,13 @@
|
||||
"titlePlaceholder": "Title",
|
||||
"valuePlaceholder": "Value"
|
||||
},
|
||||
"slider": {
|
||||
"default": "Default Value",
|
||||
"name": "Slider",
|
||||
"min": "Min Value",
|
||||
"max": "Max Value",
|
||||
"step": "Step Size"
|
||||
},
|
||||
"email": {
|
||||
"default": "Default Email",
|
||||
"name": "Email"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user