Skip to content

Commit

Permalink
fix(inputNumber): correct onChange, onOverlimit event triggering timi…
Browse files Browse the repository at this point in the history
…ng when async & sync (#2509)

* fix(inputNumber): onOverlimit and onchange

* fix(inputNumber): onOverlimit and onchange

* chore: unify demo

* chore: add test

* chore: add test

* fix: not overlimit

* fix: reset demo

* fix: test
  • Loading branch information
Alex-huxiyang authored Aug 2, 2024
1 parent 62809a0 commit 4c20ed7
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 25 deletions.
17 changes: 17 additions & 0 deletions src/packages/inputnumber/__tests__/inputnumber.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,20 @@ test('allowEmpty', () => {
expect(container.querySelector('input')?.value).toBe('')
})
})

test('should overlimit when input', () => {
const change = vi.fn()
const overlimit = vi.fn()
const { container } = render(
<InputNumber
defaultValue={2}
max={100}
onChange={change}
onOverlimit={overlimit}
/>
)
const input = container.querySelectorAll('input')[0]
input.value = '200'
fireEvent.input(input)
expect(change).toBeCalled()
})
12 changes: 10 additions & 2 deletions src/packages/inputnumber/demos/h5/demo3.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,19 @@ import React from 'react'
import { InputNumber, Toast } from '@nutui/nutui-react'

const Demo3 = () => {
const overlimit = () => {
const overlimit = (e: any) => {
Toast.show({ content: '超出限制事件触发', icon: 'warn' })
}
return (
<InputNumber defaultValue={10} min={10} max={20} onOverlimit={overlimit} />
<InputNumber
defaultValue={10}
min={10}
max={20}
onOverlimit={overlimit}
onChange={(v) => {
console.log('onChange', v)
}}
/>
)
}
export default Demo3
15 changes: 14 additions & 1 deletion src/packages/inputnumber/demos/h5/demo8.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,26 @@ import { InputNumber, Toast } from '@nutui/nutui-react'

const Demo8 = () => {
const [inputValue, setInputValue] = useState(0)
const overlimit = (e: any) => {
console.log('超出限制事件触发', e)
}
const onChange = (value: string | number) => {
Toast.show({ icon: 'loading', content: '异步演示2秒后更改' })
console.log('onChange', value)
setTimeout(() => {
setInputValue(Number(value))
Toast.clear()
}, 2000)
}
return <InputNumber value={inputValue} min={-6} onChange={onChange} async />
return (
<InputNumber
value={inputValue}
min={-6}
max={6}
onChange={onChange}
onOverlimit={overlimit}
async
/>
)
}
export default Demo8
3 changes: 3 additions & 0 deletions src/packages/inputnumber/demos/taro/demo3.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ const Demo3 = () => {
min={10}
max={20}
onOverlimit={overlimit}
onChange={(v) => {
console.log('onChange', v)
}}
/>
<Toast
type={toastType}
Expand Down
13 changes: 12 additions & 1 deletion src/packages/inputnumber/demos/taro/demo8.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,27 @@ const Demo8 = () => {
SetToastType(type)
SetShow(true)
}
const overlimit = (e: any) => {
console.log('超出限制事件触发', e)
}
const onChange = (value: string | number) => {
toastShow('异步演示 2 秒后更改', 'loading')
console.log('onChange', value)
setTimeout(() => {
setInputValue(Number(value))
SetShow(false)
}, 2000)
}
return (
<>
<InputNumber value={inputValue} min="-6" onChange={onChange} async />
<InputNumber
value={inputValue}
min={-6}
max={6}
onChange={onChange}
onOverlimit={overlimit}
async
/>
<Toast
type={toastType}
visible={show}
Expand Down
45 changes: 34 additions & 11 deletions src/packages/inputnumber/inputnumber.taro.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export interface InputNumberProps extends BasicComponent {
formatter?: (value?: string | number) => string
onPlus: (e: React.MouseEvent) => void
onMinus: (e: React.MouseEvent) => void
onOverlimit: (e: React.MouseEvent) => void
onOverlimit: (e: React.MouseEvent | ChangeEvent<HTMLInputElement>) => void
onBlur: (e: React.FocusEvent<HTMLInputElement>) => void
onFocus: (e: React.FocusEvent<HTMLInputElement>) => void
onChange: (
Expand Down Expand Up @@ -181,7 +181,25 @@ export const InputNumber: FunctionComponent<
if (text === '-') return null
return text
}
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const clampValue = (valueStr: string | null) => {
if (valueStr === null) return defaultValue
const val = Number(parseFloat(valueStr || '0').toFixed(digits))
return Math.max(Number(min), Math.min(Number(max), val))
}
const handleValueChange = (
valueStr: string | null,
e: React.ChangeEvent<HTMLInputElement>
) => {
const val = clampValue(valueStr)
// input暂不触发onOverlimit
// if (val !== Number(e.target.value)) {
// onOverlimit?.(e)
// }
if (val !== Number(shadowValue)) {
onChange?.(val, e)
}
}
const handleInputChange = (e: ChangeEvent<HTMLInputElement>) => {
// 设置 input 值, 在 blur 时格式化
setInputValue(e.target.value)
const valueStr = parseValue(e.target.value)
Expand All @@ -192,11 +210,9 @@ export const InputNumber: FunctionComponent<
setShadowValue(defaultValue)
}
} else {
setShadowValue(valueStr as any)
}
if (!async) {
onChange?.(parseFloat(valueStr || '0').toFixed(digits) as any, e)
setShadowValue(clampValue(valueStr) as any)
}
!async && handleValueChange(valueStr, e)
}
const handleFocus = (e: React.FocusEvent<HTMLInputElement>) => {
setFocused(true)
Expand All @@ -205,15 +221,22 @@ export const InputNumber: FunctionComponent<
? bound(Number(shadowValue), Number(min), Number(max)).toString()
: ''
)
onFocus && onFocus(e)
onFocus?.(e)
}
const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => {
setFocused(false)
onBlur && onBlur(e)
if (async) {
const valueStr = parseValue(e.target.value)
onChange?.(parseFloat(valueStr || '0').toFixed(digits) as any, e)
onBlur?.(e)
const valueStr = parseValue(e.target.value)
if (valueStr === null) {
if (allowEmpty) {
setShadowValue(null)
} else {
setShadowValue(defaultValue)
}
} else {
setShadowValue(clampValue(valueStr) as any)
}
async && handleValueChange(valueStr, e)
}

return (
Expand Down
43 changes: 33 additions & 10 deletions src/packages/inputnumber/inputnumber.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export interface InputNumberProps extends BasicComponent {
formatter?: (value?: string | number) => string
onPlus: (e: React.MouseEvent) => void
onMinus: (e: React.MouseEvent) => void
onOverlimit: (e: React.MouseEvent) => void
onOverlimit: (e: React.MouseEvent | ChangeEvent<HTMLInputElement>) => void
onBlur: (e: React.FocusEvent<HTMLInputElement>) => void
onFocus: (e: React.FocusEvent<HTMLInputElement>) => void
onChange: (
Expand Down Expand Up @@ -177,6 +177,24 @@ export const InputNumber: FunctionComponent<
if (text === '-') return null
return text
}
const clampValue = (valueStr: string | null) => {
if (valueStr === null) return defaultValue
const val = Number(parseFloat(valueStr || '0').toFixed(digits))
return Math.max(Number(min), Math.min(Number(max), val))
}
const handleValueChange = (
valueStr: string | null,
e: React.ChangeEvent<HTMLInputElement>
) => {
const val = clampValue(valueStr)
// input暂不触发onOverlimit
// if (val !== Number(e.target.value)) {
// onOverlimit?.(e)
// }
if (val !== Number(shadowValue)) {
onChange?.(val, e)
}
}
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
// 设置 input 值, 在 blur 时格式化
setInputValue(e.target.value)
Expand All @@ -188,11 +206,9 @@ export const InputNumber: FunctionComponent<
setShadowValue(defaultValue)
}
} else {
setShadowValue(valueStr as any)
}
if (!async) {
onChange?.(parseFloat(valueStr || '0').toFixed(digits) as any, e)
setShadowValue(clampValue(valueStr) as any)
}
!async && handleValueChange(valueStr, e)
}
const handleFocus = (e: React.FocusEvent<HTMLInputElement>) => {
setFocused(true)
Expand All @@ -201,15 +217,22 @@ export const InputNumber: FunctionComponent<
? bound(Number(shadowValue), Number(min), Number(max)).toString()
: ''
)
onFocus && onFocus(e)
onFocus?.(e)
}
const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => {
setFocused(false)
onBlur && onBlur(e)
if (async) {
const valueStr = parseValue(e.target.value)
onChange?.(parseFloat(valueStr || '0').toFixed(digits) as any, e)
onBlur?.(e)
const valueStr = parseValue(e.target.value)
if (valueStr === null) {
if (allowEmpty) {
setShadowValue(null)
} else {
setShadowValue(defaultValue)
}
} else {
setShadowValue(clampValue(valueStr) as any)
}
async && handleValueChange(valueStr, e)
}

return (
Expand Down

0 comments on commit 4c20ed7

Please sign in to comment.