如何确保 TextField 最多接受 255 个字符并在超出时显示警告?

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

我想要这个来自 Macial UI Text Field 的 TextField 组件

<TextField
  value={value}
  label='Ana iş Adımı'
  multiline
  onChange={onChange}
  placeholder=' '
  error={Boolean(errors.definition)}
  aria-describedby='validation-basic-definition'
  sx={{ mb: 2, backgroundColor: isUpdateMode && '#EBF3F7', rounded: 4 }}
 />

最大长度为 255 个字符。如果超过 255 个字符的限制,我希望在下面显示一条红色警告消息,如下图所示:pic,但我不想只包含

<TextField
  ...
  inputProps={{ maxLength: 255 }}
/>

到文本字段,因为它不显示红色警告消息。它仅强制执行字符限制。我的整个页面是:

import React, {useEffect, useState} from "react";

import Grid from "@mui/material/Grid";
import Typography from "@mui/material/Typography";
import Box from "@mui/material/Box";
import Tooltip from "@mui/material/Tooltip";
import IconButton from "@mui/material/IconButton";
import Icon from "../../../@core/components/icon";
import {Controller, useForm} from "react-hook-form";
import restClient from "../../../rest/client";
import mappings from "../../../mappings/mapping";
import toast from "react-hot-toast";
import Card from "@mui/material/Card";
import CardHeader from "@mui/material/CardHeader";
import CardContent from "@mui/material/CardContent";
import FormControl from "@mui/material/FormControl";
import TextField from "@mui/material/TextField";
import FormHelperText from "@mui/material/FormHelperText";
import InputLabel from "@mui/material/InputLabel";
import Select from "@mui/material/Select";
import MenuItem from "@mui/material/MenuItem";
import Button from "@mui/material/Button";
import {
    DataGrid, gridPageCountSelector, GridPagination,
    GridToolbarContainer,
    GridToolbarExport,
    GridToolbarFilterButton, GridToolbarQuickFilter,
    useGridApiContext, useGridSelector
} from "@mui/x-data-grid";
import DeleteDialog from "../../../views/components/company/DeleteDialog";
import MuiPagination from "@mui/material/Pagination";
import secureLocalStorage from "react-secure-storage";

const defaultValues = {
    id: '',
    definition: '',
    orderNo: '',
    companyRequest: null,
};

function CustomToolbar() {
    return (
        <GridToolbarContainer>
            <GridToolbarQuickFilter/>
        </GridToolbarContainer>
    );
}

function Pagination({page, onPageChange, className}) {
    const apiRef = useGridApiContext();
    const pageCount = useGridSelector(apiRef, gridPageCountSelector);

    return (
        <MuiPagination
            color="warning"
            className={className}
            count={pageCount}
            page={page + 1}
            onChange={(event, newPage) => {
                onPageChange(event, newPage - 1);
            }}
        />
    );
}

function CustomPagination(props) {
    return <GridPagination ActionsComponent={Pagination} {...props} />;
}

const CompanyJobDescription = () => {
    const [companyJobDescriptionLList, setCompanyJobDescriptionList] = useState([]);
    const [selectedId, setSelectedId] = useState();
    const [openDelete, setOpenDelete] = useState(false);
    const [isUpdateMode, setIsUpdateMode] = useState(false);

    const {
        control,
        handleSubmit,
        formState: { errors },
        reset,
        setValue,
        watch: valueWatch
    } = useForm({
        defaultValues,
    });

    const columns = [
        {
            flex: 0.01,
            minWidth: 100,
            headerName: 'S.N',
            field: 'orderNo',
            renderCell: (params) => (
                <Typography variant="body2" sx={{ color: 'text.primary' }}>
                    {params.row.orderNo}
                </Typography>
            )
        },
        {
            flex: 1,
            minWidth: 200,
            field: 'definition',
            headerName: 'Ana İş Adımı',
            renderCell: (params) => (
                <Typography
                    variant="body2"
                    sx={{ color: 'text.primary', whiteSpace: 'pre-wrap', overflow: 'auto', maxHeight: '50px', pt: 1 }}
                >
                    {params.row.definition}
                </Typography>
            )
        },
        {
            flex: 0.05,
            minWidth: 140,
            field: 'actions',
            headerName: 'İşlemler',
            renderCell: (params) => {
                const id = valueWatch("id");

                return (
                    <Box sx={{ display: 'flex', alignItems: 'center' }}>
                        <Tooltip title="Düzenle">
                            <IconButton
                                size="small"
                                color="warning"
                                sx={{ mr: 0.5 }}
                                onClick={() => updateJobDescription(params)}
                            >
                                <Icon icon="mi:edit" />
                            </IconButton>
                        </Tooltip>
                        <Tooltip title="Sil">
                            <IconButton
                                size="small"
                                color="error"
                                onClick={() => showDeleteModal(params)}
                            >
                                <Icon icon="mdi:delete-outline" />
                            </IconButton>
                        </Tooltip>
                        {id === params.row.id && (
                            <Tooltip title='Güncellemeyi İptal Et'>
                                <IconButton size='small' color="error" onClick={resetForm}>
                                    <Icon icon='material-symbols:cancel-outline' />
                                </IconButton>
                            </Tooltip>
                        )}
                    </Box>
                );
            }
        }
    ];

    const handleConfirmDelete = () => {
        deleteCompanyJobDescription(selectedId);
        setOpenDelete(false);
    };

    const updateJobDescription = params => {
        const { id, definition, orderNo } = params.row;
        setValue('id', id);
        setValue('orderNo', orderNo);
        setValue('definition', definition);
        setIsUpdateMode(true); // Güncelleme modunu etkinleştir
    };

    const showDeleteModal = (params) => {
        setSelectedId(params.row.id);
        setOpenDelete(true);
    };

    const deleteCompanyJobDescription = (selectedId) => {
        restClient.delete(mappings.companyJobDescription.deleteCompanyJob(selectedId)).then(() => {
            getCompanyJobDescription();
            setOpenDelete(false);
            toast.success("Görev Tanımı başarıyla silindi.");
        }).catch(() => {
            toast.error("Görev Tanımı silinirken hata oluştu.");
        });
    };

    const getCompanyJobDescription = () => {
        const company = JSON.parse(secureLocalStorage.getItem("companyInfo"));
        restClient.get(mappings.companyJobDescription.getCompanyJobDescriptionByCompanyId(company?.id)).then(res => {
            setCompanyJobDescriptionList(res.data.data);
        });
    };

    useEffect(getCompanyJobDescription, []);

    const onSubmit = (companyJobDescription) => {
        companyJobDescription.companyRequest = JSON.parse(secureLocalStorage.getItem("companyInfo"));

        const isOrderNoUnique = !companyJobDescriptionLList.some(
            (item) => item.orderNo === parseInt(companyJobDescription.orderNo) && item.id !== companyJobDescription.id
        );

        if (!isOrderNoUnique) {
            toast.error("Bu sıra numarası zaten mevcut. Lütfen farklı bir sıra numarası girin.");
            
return;
        }

        restClient.post(mappings.companyJobDescription.addCompanyJobDescription(), companyJobDescription)
            .then(() => {
                toast.success("Görev Tanımı başarıyla kaydedildi.");
                getCompanyJobDescription();
                resetForm();
            }).catch((error) => {
            console.error("Görev Tanımı oluşturulurken bir hata oluştu: ", error);
            toast.error("Görev Tanımı oluşturulurken hata oluştu.");
        });
    };

    const resetForm = () => {
        reset();
        setIsUpdateMode(false); // Güncelleme modunu kapat
    };

    return (
        <>
            <Card sx={{ mb: 2 }}>
                <CardHeader
                    sx={{ mb: 0 }}
                    title="Görev Tanımı Jenerik Maddeleri Ekle"
                    avatar={
                        <IconButton>
                            <Icon icon={isUpdateMode ? 'mi:edit' : 'mdi:plus'} />
                        </IconButton>
                    }
                />
                <CardContent>
                    <Grid sx={{ pb: 5 }}>
                        <form onSubmit={handleSubmit(onSubmit)}>
                            <Grid container spacing={5}>
                                <Grid item xs={12} sm={12}>
                                    <FormControl fullWidth>
                                        <Controller
                                            name='orderNo'
                                            control={control}
                                            rules={{ required: true }}
                                            render={({ field: { value, onChange } }) => (
                                                <TextField
                                                    value={value}
                                                    label='Sıra Numarası'
                                                    onChange={onChange}
                                                    placeholder=' '
                                                    error={Boolean(errors.orderNo)}
                                                    aria-describedby='validation-basic-orderNo'
                                                    sx={{ mb: 2, backgroundColor: isUpdateMode && '#EBF3F7', rounded: 4 }}
                                                />
                                            )}
                                        />
                                        {errors.orderNo && (
                                            <FormHelperText sx={{ color: 'error.main' }} id='validation-basic-orderNo'>
                                                Bu alan zorunlu.
                                            </FormHelperText>
                                        )}
                                    </FormControl>
                                </Grid>

                                <Grid item xs={12} sm={12}>
                                    <FormControl fullWidth>
                                        <Controller
                                            name='definition'
                                            control={control}
                                            rules={{ required: true }}
                                            render={({ field: { value, onChange } }) => (
                                                <TextField
                                                    value={value}
                                                    label='Ana iş Adımı'
                                                    multiline
                                                    onChange={onChange}
                                                    placeholder=' '
                                                    error={Boolean(errors.definition)}
                                                    aria-describedby='validation-basic-definition'
                                                    sx={{ mb: 2, backgroundColor: isUpdateMode && '#EBF3F7', rounded: 4 }}
                                                />
                                            )}
                                        />
                                        {errors.definition && (
                                            <FormHelperText sx={{ color: 'error.main' }} id='validation-basic-definition'>
                                                Bu alan zorunlu.
                                            </FormHelperText>
                                        )}
                                    </FormControl>
                                </Grid>

                                <Grid item xs={12} sm={12} sx={{ display: 'flex' }}>
                                    <Button fullWidth size='large' type='submit' variant='contained'>
                                        {isUpdateMode ? "Güncelle" : "Kaydet"}
                                    </Button>
                                </Grid>
                            </Grid>
                        </form>
                    </Grid>
                    <Box sx={{ height: 700 }}>
                        <DataGrid
                            columns={columns}
                            rowsPerPageOptions={[7, 10, 25, 50]}
                            rows={companyJobDescriptionLList}
                            sortModel={[
                                {
                                    field: 'orderNo',
                                    sort: 'asc',
                                },
                            ]}
                            slots={{
                                toolbar: CustomToolbar,
                                pagination: CustomPagination,
                            }}
                            pagination
                            getRowHeight={() => "auto"}
                        />
                    </Box>
                </CardContent>
            </Card>

            <DeleteDialog onConfirm={handleConfirmDelete} open={openDelete} setOpen={setOpenDelete} />
        </>
    );
}

export default CompanyJobDescription;

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.3.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.3.1/umd/react-dom.production.min.js"></script>

我是 stackoverflow 的新用户。如果我在提问时犯了错误,我深表歉意。

reactjs material-ui textfield
1个回答
0
投票

你可以做类似的事情

...
const [text, setText] = useState("");
const [error, setError] = useState(false);

const handleChange = (event) => {
  const value = event.target.value;
  if (value.length <= 255) {
    setText(value);
    setError(false);
  } else {
    setError(true);
  }
};
...
return (
   ...
      <TextField
        ...
        value={value}
        onChange={handleChange}
        error={error}
      />
      {error && (
        <Typography variant="caption" color="error">
          Maximum character limit is 255
        </Typography>
      )}
© www.soinside.com 2019 - 2024. All rights reserved.