如何在 Joy UI 的自定义 Textarea 组件中设置 maxLength?

问题描述 投票:0回答:1

我正在 React 中构建这个自定义 Textarea 组件,它将显示在 Storybook 中。 不知何故,我无法使其与该组件的 maxLength 道具一起使用,因为我可以编写一个在设置道具时超出 maxLength 的用户输入。即使我将 maxLength 硬编码为例如 10,我仍然可以超过该 maxLength。

这是我的组件代码:

import { FormControl, FormHelperText, Grid, Textarea, TextareaProps, Typography } from "@mui/joy";
import Image from "next/image";
import errorhelper from "../../../public/errorhelper.svg";
import search from "../../../public/search.svg";
import { InnerTextarea } from "./styles/TextAreaStyles";

type TextAreaBaseProps = Pick<TextareaProps, "disabled" | "error" | "value" | "onChange"> & {
    /**If true the icon is shown in the start of the textfield */
    showIcon: boolean;
    /**If true the textfield is optional */
    optional: boolean;
    /**Shows the textfield in focus state */
    focus?: boolean;
    /**The helper text for input field in default state*/
    helperText?: string;
    /**The helper text for input field in error state */
    errorHelperText?: string;
    /**The label for the input field */
    label: string;
    /**The maximum length of the inputfield */
    maxLength?: number;
};

/** A custom textarea component using Joy-UI's Textarea */
export const TextAreaField = ({
    showIcon,
    optional,
    focus,
    helperText,
    errorHelperText,
    label,
    maxLength,
    ...props
}: TextAreaBaseProps) => {
    return (
        <FormControl>
            <Textarea
                {...props}
                minRows={6}
                sx={{
                    display: "flex",
                    width: "19.125rem",
                    ...(focus && {
                        outline: "0.125rem solid var(--colorSystemColorsFocus500)",
                        outlineOffset: "-0.0625rem"
                    }),
                    "& .css-1p7e9sy-JoyTextarea-startDecorator": {
                        marginBlockEnd: 0
                    }
                }}
                startDecorator={
                    <Grid container direction={"row"} justifyContent={"space-between"} width={"19.125rem"}>
                        <Grid marginTop={0.5}>{showIcon && <Image src={search} alt={""} width={16} height={16} />}</Grid>
                        <Grid>
                            {optional && (
                                <Typography sx={{ ml: 1, color: "var(--colorTextDefault)" }}>(Optional)</Typography>
                            )}
                        </Grid>
                    </Grid>
                }
                slotProps={{
                    textarea: {
                        ...(maxLength && { maxLength })
                    }
                }}
                slots={{
                    textarea: () => <InnerTextarea {...props} showIcon={showIcon} label={label} />
                }}
            />
            <Grid container direction={"row"} justifyContent={"space-between"} width={"19.125rem"}>
                <Grid>
                    {props.error ? (
                        <FormHelperText sx={{ color: "var(--colorSystemColorsDanger500)" }}>
                            <Image src={errorhelper} alt={""} width={16} height={16} /> {errorHelperText}
                        </FormHelperText>
                    ) : (
                        helperText && <FormHelperText>{helperText}</FormHelperText>
                    )}
                </Grid>
                <Grid>
                    {maxLength && (
                        <FormHelperText>
                            {props.value?.toString().length}/{maxLength}
                        </FormHelperText>
                    )}
                </Grid>
            </Grid>
        </FormControl>
    );
};

这是添加到组件中的一些样式,取自此处:https://mui.com/joy-ui/react-textarea/#floating-label

import { styled } from "@mui/joy";
import { TextareaAutosize } from "@mui/base/TextareaAutosize";
import React from "react";

const StyledTextarea = styled(TextareaAutosize)({
    resize: "none",
    border: "none", // remove the native textarea border
    minWidth: 0, // remove the native textarea width
    outline: 0, // remove the native textarea outline
    padding: 0, // remove the native textarea padding
    paddingBlockStart: 0,
    paddingInlineEnd: 0,
    flex: "auto",
    alignSelf: "stretch",
    color: "inherit",
    backgroundColor: "transparent",
    fontFamily: "inherit",
    fontSize: "inherit",
    fontStyle: "inherit",
    fontWeight: "inherit",
    lineHeight: "inherit",
    "&::placeholder": {
        opacity: 0,
        transition: "0.1s ease-out"
    },
    "&:focus::placeholder": {
        opacity: 1
    }
});

const StyledLabel = styled("label")(({ theme }) => ({
    position: "absolute",
    lineHeight: 1,
    top: "calc((var(--Textarea-minHeight) - 1em) / 2)",
    color: "var(--colorTextSubtle1)",
    transition: "all 150ms cubic-bezier(0.4, 0, 0.2, 1)"
}));

export const InnerTextarea = React.forwardRef<
    HTMLTextAreaElement,
    React.JSX.IntrinsicElements["textarea"] & { showIcon: boolean; label: string }
>(function InnerTextarea({ showIcon, label, ...props }, ref) {
    const id = React.useId();
    console.log(props.value);
    return (
        <React.Fragment>
            <StyledTextarea minRows={2} {...props} ref={ref} id={id} />
            <StyledLabel
                sx={{
                    marginLeft: showIcon ? "1rem" : 0,
                    fontSize: props.value ? "0.75rem" : "1rem",
                    top: props.value ? "0.5rem" : null
                }}
                htmlFor={id}>
                {label}
            </StyledLabel>
        </React.Fragment>
    );
});

所示问题

reactjs typescript material-ui textarea
1个回答
0
投票

您需要通过检查

onChange
功能并检查长度是否小于允许的最大长度来限制用户输入。像这样的事情:-

 <StyledTextarea minRows={2} {...props} ref={ref} id={id} onChange={(e) => { if(e.target.value.length > 10) { setValue(e.target.value)}}}/>
© www.soinside.com 2019 - 2024. All rights reserved.