Integer and Numeric inputs fixes.

pull/58/head
Aditya Toshniwal 2021-08-30 17:01:49 +05:30 committed by Akshay Joshi
parent 73e1cbc0b9
commit af27af8d42
3 changed files with 34 additions and 54 deletions

View File

@ -34,28 +34,6 @@ function MappedFormControlBase({type, value, id, onChange, className, visible, i
onChange && onChange(value); 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) { if(!visible) {
return <></>; return <></>;
} }
@ -63,9 +41,9 @@ function MappedFormControlBase({type, value, id, onChange, className, visible, i
/* The mapping uses Form* components as it comes with labels */ /* The mapping uses Form* components as it comes with labels */
switch (type) { switch (type) {
case 'int': 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': 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': case 'text':
return <FormInputText name={name} value={value} onChange={onTextChange} className={className} inputRef={inputRef} {...props}/>; return <FormInputText name={name} value={value} onChange={onTextChange} className={className} inputRef={inputRef} {...props}/>;
case 'multiline': case 'multiline':
@ -131,28 +109,6 @@ function MappedCellControlBase({cell, value, id, optionsLoaded, onCellChange, vi
onCellChange && onCellChange(value); 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. /* Some grid cells are based on options selected in other cells.
* lets trigger a re-render for the row if optionsLoaded * 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 */ /* The mapping does not need Form* components as labels are not needed for grid cells */
switch(cell) { switch(cell) {
case 'int': case 'int':
return <InputText name={name} value={value} onChange={onIntChange} {...props}/>; return <InputText name={name} value={value} onChange={onTextChange} {...props} type='int'/>;
case 'numeric': case 'numeric':
return <InputText name={name} value={value} onChange={onNumChange} {...props}/>; return <InputText name={name} value={value} onChange={onTextChange} {...props} type='numeric'/>;
case 'text': case 'text':
return <InputText name={name} value={value} onChange={onTextChange} {...props}/>; return <InputText name={name} value={value} onChange={onTextChange} {...props}/>;
case 'password': case 'password':

View File

@ -291,11 +291,22 @@ FormInputDateTimePicker.propTypes = {
/* Use forwardRef to pass ref prop to OutlinedInput */ /* Use forwardRef to pass ref prop to OutlinedInput */
export const InputText = forwardRef(({ 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 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) { if(controlProps?.formatter) {
changeVal = controlProps.formatter.toRaw(changeVal); changeVal = controlProps.formatter.toRaw(changeVal);
} }
@ -317,6 +328,7 @@ export const InputText = forwardRef(({
id: cid, id: cid,
maxLength: maxlength, maxLength: maxlength,
'aria-describedby': helpid, 'aria-describedby': helpid,
...(type ? {pattern: patterns[type]} : {})
}} }}
readOnly={Boolean(readonly)} readOnly={Boolean(readonly)}
disabled={Boolean(disabled)} disabled={Boolean(disabled)}
@ -326,6 +338,7 @@ export const InputText = forwardRef(({
onChange={onChangeFinal} onChange={onChangeFinal}
{...controlProps} {...controlProps}
{...props} {...props}
{...(['numeric', 'int'].indexOf(type) > -1 ? {type: 'tel'} : {})}
/> />
); );
}); });
@ -340,6 +353,7 @@ InputText.propTypes = {
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
onChange: PropTypes.func, onChange: PropTypes.func,
controlProps: PropTypes.object, controlProps: PropTypes.object,
type: PropTypes.string,
}; };
export function FormInputText({hasError, required, label, className, helpMessage, testcid, ...props}) { export function FormInputText({hasError, required, label, className, helpMessage, testcid, ...props}) {

View File

@ -43,6 +43,16 @@ function getSchemaAllTypes() {
describe('SchemaView', ()=>{ describe('SchemaView', ()=>{
let mount; let mount;
let numberChangeEvent = (value)=>{
return {
target: {
value: value,
validity: {
valid: true,
}
}
};
};
/* Use createMount so that material ui components gets the required context */ /* Use createMount so that material ui components gets the required context */
/* https://material-ui.com/guides/testing/#api */ /* https://material-ui.com/guides/testing/#api */
@ -91,7 +101,7 @@ describe('SchemaView', ()=>{
}, },
simulateValidData = ()=>{ simulateValidData = ()=>{
ctrl.find('MappedFormControl[id="field1"]').find('input').simulate('change', {target: {value: 'val1'}}); 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'}}); ctrl.find('MappedFormControl[id="field5"]').find('textarea').simulate('change', {target: {value: 'val5'}});
/* Add a row */ /* Add a row */
ctrl.find('DataGridView').find('PgIconButton[data-test="add-row"]').find('button').simulate('click'); ctrl.find('DataGridView').find('PgIconButton[data-test="add-row"]').find('button').simulate('click');
@ -117,7 +127,7 @@ describe('SchemaView', ()=>{
}); });
it('change text', (done)=>{ 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(()=>{ setTimeout(()=>{
ctrl.update(); ctrl.update();
/* Error should come for field1 as it is empty and noEmpty true */ /* Error should come for field1 as it is empty and noEmpty true */
@ -210,7 +220,7 @@ describe('SchemaView', ()=>{
}); });
it('data invalid', (done)=>{ 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'); ctrl.find('ForwardRef(Tab)[label="SQL"]').find('button').simulate('click');
setTimeout(()=>{ setTimeout(()=>{
ctrl.update(); ctrl.update();
@ -240,7 +250,7 @@ describe('SchemaView', ()=>{
expect(onSave.calls.argsFor(0)[1]).toEqual({ expect(onSave.calls.argsFor(0)[1]).toEqual({
id: undefined, id: undefined,
field1: 'val1', field1: 'val1',
field2: 2, field2: '2',
field5: 'val5', field5: 'val5',
fieldcoll: [ fieldcoll: [
{field3: null, field4: null, field5: 'rval51'}, {field3: null, field4: null, field5: 'rval51'},