【发布时间】:2023-02-09 13:14:09
【问题描述】:
我有创建输入字段的要求,它采用数字数组(逗号','分隔),如 [123,34,23,13]。
我希望当用户将此 123,34,23,13 复制到输入字段时,它应该根据逗号更改为以下格式。
无论如何要实现这一点。
稍后我想为不正确的数字显示红旗(这将在提交值时进行验证)。
【问题讨论】:
标签: reactjs material-ui components chips
我有创建输入字段的要求,它采用数字数组(逗号','分隔),如 [123,34,23,13]。
我希望当用户将此 123,34,23,13 复制到输入字段时,它应该根据逗号更改为以下格式。
无论如何要实现这一点。
稍后我想为不正确的数字显示红旗(这将在提交值时进行验证)。
【问题讨论】:
标签: reactjs material-ui components chips
这个jsFiddle demo符合你的要求吗? (单击“运行”开始演示。)如果没有,请告诉我缺少什么。
该演示仅接受逗号分隔的整数(或单个整数)作为输入。不允许有空格。
重复值以红色条显示,不包含在结果集中。到目前为止,重复值是导致值失败的唯一验证标准,其中失败通过红筹码显示给用户。
非数字输入静默失败。
<!DOCTYPE html>
<html>
<head>
<title>Material-UI Chip Input Field Test</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id="testContainer" class="testContainer"></div>
<script src="./index.js"></script>
<noscript> Please enable javascript to view the site </noscript>
</body>
</html>
import * as React from 'react';
import { createRoot } from 'react-dom/client';
const container = document.getElementById( 'testContainer' );
const root = createRoot( container );
import Chip from '@mui/material/Chip';
import Autocomplete from '@mui/material/Autocomplete';
import TextField from '@mui/material/TextField';
import Stack from '@mui/material/Stack';
import { v4 as uuidv4 } from 'uuid';
let collator = new Intl.Collator( 'en', { numeric: true, sensitivity: 'base' } );
const getSortedListAsArray = ( list ) => {
let sortedList = list.sort( ( a, b ) => {
return collator.compare( a.value, b.value );
} );
return sortedList;
}
export default function Tags() {
const [ list, setList ] = React.useState( [] );
const selectedItems = list.filter( ( item ) => item.isValid );
const selectedLengthIndex = selectedItems.length - 1;
let listById = {};
for ( let item of list ) {
listById[ item.id ] = item;
}
function updateList( items ) {
let newList = [].concat( list, items );
newList = getSortedListAsArray( newList );
setList( newList );
}
function validateValue( value, validatedItems ) {
let isValid = false;
const valueInt = parseInt( value );
const selectedValues = list.map( ( item ) => item.value );
const validatedValues = validatedItems.map( ( item ) => item.value );
if ( selectedValues.indexOf( valueInt ) === -1 &&
validatedValues.indexOf( valueInt ) === -1
) {
isValid = true;
}
return isValid;
}
function validateInput( event, inputs, reason ) {
if ( 'createOption' == reason ) {
let validatedItems = [];
let values = inputs[ inputs.length - 1 ].split( ',' );
for ( let value of values ) {
// Test for positive integers. Fail silently.
if ( /[^0-9]+/.test( value ) || value.length == 0 ) {
continue;
} else {
let isValid = validateValue( value, validatedItems );
validatedItems.push( {
id: uuidv4(),
value: parseInt( value ),
isValid
} );
}
}
updateList( validatedItems );
} else if ( 'removeOption' == reason ) {
let newList = inputs.map( ( id ) => listById[ id ] );
setList( newList );
} else if ( 'clear' == reason ) {
setList( [] );
}
}
/**
* Return call adapted from Material-UI 'Multiple values' Autocomplete demo.
* @see https://mui.com/material-ui/react-table/#sorting-amp-selecting
* Code: @see https://github.com/mui/material-ui/blob/v5.9.2/docs/data/material/components/autocomplete/Tags.tsx
*
*/
return (
<Stack spacing={ 3 } sx={ { width: 500 } }>
<Autocomplete
multiple
id='tags-filled'
filterSelectedOptions={ true }
options={ [] }
value={ list.map( ( item ) => item.id ) }
freeSolo
renderTags={ ( listIds, getTagProps ) =>
listIds.map( ( id, index ) => (
<Chip
key={ index }
variant='outlined'
label={ listById[ id ].value }
sx={ {
color: ( theme ) => {
let chipColor = '#fff';
if ( typeof( listById[ id ] ) == 'object' ) {
chipColor = listById[ id ].isValid
? theme.palette.common.white
: theme.palette.common.white
}
return chipColor;
},
backgroundColor: ( theme ) => {
let chipColor = '#fff';
if ( typeof( listById[ id ] ) == 'object' ) {
chipColor = listById[ id ].isValid
? theme.palette.primary.main
: theme.palette.error.main
}
return chipColor;
},
[`& .MuiSvgIcon-root.MuiSvgIcon-fontSizeMedium.MuiChip-deleteIcon.MuiChip-deleteIconMedium.MuiChip-deleteIconColorDefault.MuiChip-deleteIconOutlinedColorDefault`]: {
fill: ( theme ) => theme.palette.grey[200]
}
} }
{ ...getTagProps( { index } ) }
/>
) )
}
renderInput={ ( params ) => (
<TextField
{ ...params }
variant='filled'
label='Material-UI Chip Input Test'
placeholder='e.g. 12,73,902,23,41'
helperText='Enter comma separated integers (no spaces)'
/>
) }
onChange={ validateInput }
/>
{ /* Display list of unique integers. */ }
<div>
{ selectedItems.map( ( item, index ) => {
let comma = null;
if ( selectedLengthIndex != index ) {
comma = ( <span key={ 'idx' + index }>, </span> );
}
return (
item.isValid
? <span key={ index }>{ item.value }{ comma }</span>
: null
);
} ) }
</div>
</Stack>
);
}
/**
* Inject component into DOM
*/
root.render(
<Tags />
);
【讨论】:
这是我到目前为止发现的:https://codesandbox.io/s/quirky-waterfall-5ebi3y?file=/src/Chips.jsx
当 API 返回错误/无效的输入数组时缺少部分,那么它应该转换为红旗
【讨论】: