前缀不允许使用MUI TextField在NumericFormat上显示值



NumericFormat与MUI TextField和前缀prop一起使用。当我开始写任何数字时,我不能写多于一个数字。如果我写得快,这次我可以写所有的数字,但是前缀没有了。从键盘插入的所有数字都应该显示出来,并且不应该是任何缺失的数字,前缀应该是可见的,但这不起作用。

import { Observer } from "mobx-react-lite";
import { TextField, TextFieldProps } from "@mui/material";
import { AllowedNames } from "../utils/utils";
import { useDialogState } from "../states/dialog-state";
import { NumericFormat, NumericFormatProps } from "react-number-format";
import React from "react";
interface NumericFormatCustomProps {
onChange: (event: { target: { name: string; value: string } }) => void;
name: string;
}
const NumericFormatCustom = React.forwardRef<
NumericFormatProps<HTMLInputElement>,
NumericFormatCustomProps & NumericFormatProps<HTMLInputElement>
>(function NumericFormatCustom(props, ref) {
const { onChange, prefix, suffix, ...other } = props;
return (
<NumericFormat
{...other}
getInputRef={ref}
onValueChange={(values) => {
onChange({
target: {
name: props.name,
value: values.value,
},
});
}}
prefix={prefix}
suffix={suffix}
/>
);
});
function getValue(value: any, coefficient: number) {
if (value === "" || value === null || value === undefined) {
return "";
}
return ((value ?? 0) / Math.pow(10, coefficient)).toString();
}
function setValue(value: any, coefficient: number, decimalPlaces: number) {
if (value === "" || value === null || value === undefined) {
return null;
}
return (
(Math.round(parseFloat(value) * Math.pow(10, decimalPlaces)) /
Math.pow(10, decimalPlaces)) *
Math.pow(10, coefficient)
);
}
export type FormNumberFieldProps<T extends object> = Omit<
TextFieldProps,
"defaultValue" | "type"
> & {
dataKey: AllowedNames<T, number>;
prefix?: string;
suffix?: string;
decimalPlaces?: number;
coefficient?: number;
thousandSeparator?: boolean;
min?: number;
max?: number;
};
export default function FormNumberField<T extends object>({
dataKey,
prefix = "$ ",
suffix = "",
decimalPlaces = 0,
coefficient = 0,
thousandSeparator = true,
min,
max,
...rest
}: FormNumberFieldProps<T>) {
const [internalError, setInternalError] = React.useState("");
const stateProvider = useDialogState<T>();
const state = stateProvider.state;      
return (
<Observer>
{() => {
const value = getValue(state.getValue(dataKey) as any, coefficient);
const checkMinMax = () => {
const numberValue = parseInt(value, 10);
if (typeof min === "number") {
if (numberValue < min) {
setInternalError(`The value should be more than ${min}`);
return;
}
}
if (typeof max === "number") {
if (numberValue > max) {
setInternalError(`The value should be less than ${max}`);
return;
}
}
setInternalError("");
};
return (
<TextField
{...rest}
fullWidth
inputMode="numeric"
onBlur={checkMinMax}
value={value}
onChange={(e) => {
state.setValue(
dataKey,
setValue(e.target.value, coefficient, decimalPlaces) as any,
);
}}
error={!!internalError || !!state.errorOf(dataKey)}
helperText={internalError || state.errorOf(dataKey)}
InputLabelProps={{ shrink: true }}
InputProps={{
inputComponent: NumericFormatCustom as any,
inputProps: {
prefix,
suffix,
thousandSeparator,
},
}}
/>
);
}}
</Observer>
);
}
import { Observer } from "mobx-react-lite";
import { TextField, TextFieldProps } from "@mui/material";
import { AllowedNames } from "../utils/utils";
import { useDialogState } from "../states/dialog-state";
import { NumericFormat, NumericFormatProps } from "react-number-format";
import React from "react";
interface NumericFormatCustomProps {
onChange: (event: { target: { name: string; value: string } }) => void;
name: string;
}
const NumericFormatCustom = React.forwardRef<
NumericFormatProps<HTMLInputElement>,
NumericFormatCustomProps & NumericFormatProps<HTMLInputElement>
>(function NumericFormatCustom(props, ref) {
const { onChange, prefix, suffix, ...other } = props;
return (
<NumericFormat
{...other}
getInputRef={ref}
onValueChange={(values) => {
onChange({
target: {
name: props.name,
value: values.value,
},
});
}}
prefix={prefix}
suffix={suffix}
/>
);
});
function getValue(value: any, coefficient: number) {
if (value === "" || value === null || value === undefined) {
return "";
}
return ((value ?? 0) / Math.pow(10, coefficient)).toString();
}
function setValue(value: any, coefficient: number, decimalPlaces: number) {
if (value === "" || value === null || value === undefined) {
return null;
}
return (
(Math.round(parseFloat(value) * Math.pow(10, decimalPlaces)) /
Math.pow(10, decimalPlaces)) *
Math.pow(10, coefficient)
);
}
export type FormNumberFieldProps<T extends object> = Omit<
TextFieldProps,
"defaultValue" | "type"
> & {
dataKey: AllowedNames<T, number>;
prefix?: string;
suffix?: string;
decimalPlaces?: number;
coefficient?: number;
thousandSeparator?: boolean;
min?: number;
max?: number;
};
export default function FormNumberField<T extends object>({
dataKey,
prefix = "$ ",
suffix = "",
decimalPlaces = 0,
coefficient = 0,
thousandSeparator = true,
min,
max,
...rest
}: FormNumberFieldProps<T>) {
const [internalError, setInternalError] = React.useState("");
const stateProvider = useDialogState<T>();
const state = stateProvider.state;
// I moved here
const value = getValue(state.getValue(dataKey) as any, coefficient);
return (
<Observer>
{() => {
const checkMinMax = () => {
const numberValue = parseInt(value, 10);
if (typeof min === "number") {
if (numberValue < min) {
setInternalError(`The value should be more than ${min}`);
return;
}
}
if (typeof max === "number") {
if (numberValue > max) {
setInternalError(`The value should be less than ${max}`);
return;
}
}
setInternalError("");
};
return (
<TextField
{...rest}
fullWidth
inputMode="numeric"
onBlur={checkMinMax}
value={value}
onChange={(e) => {
state.setValue(
dataKey,
setValue(e.target.value, coefficient, decimalPlaces) as any,
);
}}
error={!!internalError || !!state.errorOf(dataKey)}
helperText={internalError || state.errorOf(dataKey)}
InputLabelProps={{ shrink: true }}
InputProps={{
inputComponent: NumericFormatCustom as any,
inputProps: {
prefix,
suffix,
thousandSeparator,
},
}}
/>
);
}}
</Observer>
);
}

最新更新