Integer and Numeric inputs fixes.
parent
73e1cbc0b9
commit
af27af8d42
|
@ -34,28 +34,6 @@ function MappedFormControlBase({type, value, id, onChange, className, visible, i
|
|||
onChange && onChange(value);
|
||||
}, []);
|
||||
|
||||
const onIntChange = useCallback((e) => {
|
||||
let value = e;
|
||||
if(e && e.target) {
|
||||
value = e.target.value;
|
||||
}
|
||||
if(!isNaN(parseInt(value))) {
|
||||
value = parseInt(value);
|
||||
}
|
||||
onChange && onChange(value);
|
||||
}, []);
|
||||
|
||||
const onNumChange = useCallback((e) => {
|
||||
let value = e;
|
||||
if(e && e.target) {
|
||||
value = e.target.value;
|
||||
}
|
||||
if(!isNaN(parseFloat(value))) {
|
||||
value = parseFloat(value);
|
||||
}
|
||||
onChange && onChange(value);
|
||||
}, []);
|
||||
|
||||
if(!visible) {
|
||||
return <></>;
|
||||
}
|
||||
|
@ -63,9 +41,9 @@ function MappedFormControlBase({type, value, id, onChange, className, visible, i
|
|||
/* The mapping uses Form* components as it comes with labels */
|
||||
switch (type) {
|
||||
case 'int':
|
||||
return <FormInputText name={name} value={value} onChange={onIntChange} className={className} inputRef={inputRef} {...props}/>;
|
||||
return <FormInputText name={name} value={value} onChange={onTextChange} className={className} inputRef={inputRef} {...props} type='int'/>;
|
||||
case 'numeric':
|
||||
return <FormInputText name={name} value={value} onChange={onNumChange} className={className} inputRef={inputRef} {...props}/>;
|
||||
return <FormInputText name={name} value={value} onChange={onTextChange} className={className} inputRef={inputRef} {...props} type='numeric'/>;
|
||||
case 'text':
|
||||
return <FormInputText name={name} value={value} onChange={onTextChange} className={className} inputRef={inputRef} {...props}/>;
|
||||
case 'multiline':
|
||||
|
@ -131,28 +109,6 @@ function MappedCellControlBase({cell, value, id, optionsLoaded, onCellChange, vi
|
|||
onCellChange && onCellChange(value);
|
||||
}, []);
|
||||
|
||||
const onIntChange = useCallback((e) => {
|
||||
let value = e;
|
||||
if(e && e.target) {
|
||||
value = e.target.value;
|
||||
}
|
||||
if(!isNaN(parseInt(value))) {
|
||||
value = parseInt(value);
|
||||
}
|
||||
onCellChange && onCellChange(value);
|
||||
}, []);
|
||||
|
||||
const onNumChange = useCallback((e) => {
|
||||
let value = e;
|
||||
if(e && e.target) {
|
||||
value = e.target.value;
|
||||
}
|
||||
if(!isNaN(parseFloat(value))) {
|
||||
value = parseFloat(value);
|
||||
}
|
||||
onCellChange && onCellChange(value);
|
||||
}, []);
|
||||
|
||||
/* Some grid cells are based on options selected in other cells.
|
||||
* lets trigger a re-render for the row if optionsLoaded
|
||||
*/
|
||||
|
@ -169,9 +125,9 @@ function MappedCellControlBase({cell, value, id, optionsLoaded, onCellChange, vi
|
|||
/* The mapping does not need Form* components as labels are not needed for grid cells */
|
||||
switch(cell) {
|
||||
case 'int':
|
||||
return <InputText name={name} value={value} onChange={onIntChange} {...props}/>;
|
||||
return <InputText name={name} value={value} onChange={onTextChange} {...props} type='int'/>;
|
||||
case 'numeric':
|
||||
return <InputText name={name} value={value} onChange={onNumChange} {...props}/>;
|
||||
return <InputText name={name} value={value} onChange={onTextChange} {...props} type='numeric'/>;
|
||||
case 'text':
|
||||
return <InputText name={name} value={value} onChange={onTextChange} {...props}/>;
|
||||
case 'password':
|
||||
|
|
|
@ -291,11 +291,22 @@ FormInputDateTimePicker.propTypes = {
|
|||
|
||||
/* Use forwardRef to pass ref prop to OutlinedInput */
|
||||
export const InputText = forwardRef(({
|
||||
cid, helpid, readonly, disabled, maxlength=255, value, onChange, controlProps, ...props}, ref)=>{
|
||||
cid, helpid, readonly, disabled, maxlength=255, value, onChange, controlProps, type, ...props}, ref)=>{
|
||||
|
||||
const classes = useStyles();
|
||||
const patterns = {
|
||||
'numeric': '^-?[0-9]\\d*\\.?\\d*$',
|
||||
'int': '^-?[0-9]\\d*$',
|
||||
};
|
||||
let onChangeFinal = (e)=>{
|
||||
let changeVal = e.target.value;
|
||||
|
||||
let onChangeFinal = (changeVal)=>{
|
||||
/* For type number, we set type as tel with number regex to get validity.*/
|
||||
if(['numeric', 'int'].indexOf(type) > -1) {
|
||||
if(!e.target.validity.valid && changeVal !== '' && changeVal !== '-') {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(controlProps?.formatter) {
|
||||
changeVal = controlProps.formatter.toRaw(changeVal);
|
||||
}
|
||||
|
@ -317,6 +328,7 @@ export const InputText = forwardRef(({
|
|||
id: cid,
|
||||
maxLength: maxlength,
|
||||
'aria-describedby': helpid,
|
||||
...(type ? {pattern: patterns[type]} : {})
|
||||
}}
|
||||
readOnly={Boolean(readonly)}
|
||||
disabled={Boolean(disabled)}
|
||||
|
@ -326,6 +338,7 @@ export const InputText = forwardRef(({
|
|||
onChange={onChangeFinal}
|
||||
{...controlProps}
|
||||
{...props}
|
||||
{...(['numeric', 'int'].indexOf(type) > -1 ? {type: 'tel'} : {})}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
@ -340,6 +353,7 @@ InputText.propTypes = {
|
|||
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
onChange: PropTypes.func,
|
||||
controlProps: PropTypes.object,
|
||||
type: PropTypes.string,
|
||||
};
|
||||
|
||||
export function FormInputText({hasError, required, label, className, helpMessage, testcid, ...props}) {
|
||||
|
|
|
@ -43,6 +43,16 @@ function getSchemaAllTypes() {
|
|||
|
||||
describe('SchemaView', ()=>{
|
||||
let mount;
|
||||
let numberChangeEvent = (value)=>{
|
||||
return {
|
||||
target: {
|
||||
value: value,
|
||||
validity: {
|
||||
valid: true,
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/* Use createMount so that material ui components gets the required context */
|
||||
/* https://material-ui.com/guides/testing/#api */
|
||||
|
@ -91,7 +101,7 @@ describe('SchemaView', ()=>{
|
|||
},
|
||||
simulateValidData = ()=>{
|
||||
ctrl.find('MappedFormControl[id="field1"]').find('input').simulate('change', {target: {value: 'val1'}});
|
||||
ctrl.find('MappedFormControl[id="field2"]').find('input').simulate('change', {target: {value: '2'}});
|
||||
ctrl.find('MappedFormControl[id="field2"]').find('input').simulate('change', numberChangeEvent('2'));
|
||||
ctrl.find('MappedFormControl[id="field5"]').find('textarea').simulate('change', {target: {value: 'val5'}});
|
||||
/* Add a row */
|
||||
ctrl.find('DataGridView').find('PgIconButton[data-test="add-row"]').find('button').simulate('click');
|
||||
|
@ -117,7 +127,7 @@ describe('SchemaView', ()=>{
|
|||
});
|
||||
|
||||
it('change text', (done)=>{
|
||||
ctrl.find('MappedFormControl[id="field2"]').find('input').simulate('change', {target: {value: '2'}});
|
||||
ctrl.find('MappedFormControl[id="field2"]').find('input').simulate('change', numberChangeEvent('2'));
|
||||
setTimeout(()=>{
|
||||
ctrl.update();
|
||||
/* Error should come for field1 as it is empty and noEmpty true */
|
||||
|
@ -210,7 +220,7 @@ describe('SchemaView', ()=>{
|
|||
});
|
||||
|
||||
it('data invalid', (done)=>{
|
||||
ctrl.find('MappedFormControl[id="field2"]').find('input').simulate('change', {target: {value: '2'}});
|
||||
ctrl.find('MappedFormControl[id="field2"]').find('input').simulate('change', numberChangeEvent('2'));
|
||||
ctrl.find('ForwardRef(Tab)[label="SQL"]').find('button').simulate('click');
|
||||
setTimeout(()=>{
|
||||
ctrl.update();
|
||||
|
@ -240,7 +250,7 @@ describe('SchemaView', ()=>{
|
|||
expect(onSave.calls.argsFor(0)[1]).toEqual({
|
||||
id: undefined,
|
||||
field1: 'val1',
|
||||
field2: 2,
|
||||
field2: '2',
|
||||
field5: 'val5',
|
||||
fieldcoll: [
|
||||
{field3: null, field4: null, field5: 'rval51'},
|
||||
|
|
Loading…
Reference in New Issue