Skip to content

Commit

Permalink
[preferences]: Input field validation
Browse files Browse the repository at this point in the history
Fixes: #7741

Added an input field validation in the preference widget.
Updated the input field type to be `number` instead of `text` for
numerical fields.

Signed-off-by: Anas Shahid <muhammad.shahid@ericsson.com>
  • Loading branch information
Anas Shahid authored and vince-fugnitto committed Aug 11, 2020
1 parent 03d297a commit 928a3bf
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 12 deletions.
30 changes: 29 additions & 1 deletion packages/preferences/src/browser/style/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -295,10 +295,38 @@
border: 1px solid var(--theia-dropdown-border);
}

.theia-settings-container .theia-input[type="checkbox"]:focus {
.theia-settings-container .theia-input[type="checkbox"]:focus,
.theia-settings-container .theia-input[type="number"]:focus {
outline-width: 2px;
}

/* Remove the spinners from input[type = number] on Firefox. */
.theia-settings-container .theia-input[type="number"] {
-webkit-appearance: textfield;
border: 1px solid var(--theia-dropdown-border);
}

/* Remove the webkit spinners from input[type = number] on all browsers except Firefox. */
.theia-settings-container input::-webkit-outer-spin-button,
.theia-settings-container input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}

.theia-settings-container .pref-content-container .pref-input .pref-input-container .pref-error-notification {
border-style: solid;
border-color: var(--theia-inputValidation-errorBorder);
background-color: var(--theia-inputValidation-errorBackground);
width: 100%;
box-sizing: border-box;
padding: var(--theia-ui-padding);
}

.theia-settings-container .pref-content-container .pref-input .pref-input-container {
display: flex;
flex-direction: column;
}

.theia-settings-container .pref-content-container a.theia-json-input {
text-decoration: underline;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,27 +31,63 @@ export const PreferenceNumberInput: React.FC<PreferenceNumberInputProps> = ({ pr

const [currentTimeout, setCurrentTimetout] = React.useState<number>(0);
const [currentValue, setCurrentValue] = React.useState<string>(externalValue);
const [validationMessage, setValidationMessage] = React.useState<string>('');

React.useEffect(() => {
setCurrentValue(externalValue);
}, [externalValue]);

const onBlur = React.useCallback(() => {
setCurrentValue(externalValue);
setValidationMessage('');
}, [externalValue]);

const onChange = React.useCallback(e => {
const { value: newValue } = e.target;
clearTimeout(currentTimeout);
const newTimeout = setTimeout(() => setPreference(id, Number(newValue)), 750);
setCurrentTimetout(Number(newTimeout));
const { value: newValue } = e.target;
setCurrentValue(newValue);
const preferenceValue: number = Number(newValue);
const { isValid, message } = getInputValidation(preferenceValue);
setValidationMessage(message);
if (isValid) {
const newTimeout = setTimeout(() => setPreference(id, preferenceValue), 750);
setCurrentTimetout(Number(newTimeout));
}
}, [currentTimeout]);

/**
* Validates the input.
* @param input the input value.
*/
const getInputValidation = (input: number | undefined): { isValid: boolean, message: string } => {
const errorMessages: string[] = [];
if (!input) {
return { isValid: false, message: 'Value must be a number.' };
};
if (data.minimum && input < data.minimum) {
errorMessages.push(`Value must be greater than or equal to ${data.minimum}.`);
};
if (data.maximum && input > data.maximum) {
errorMessages.push(`Value must be less than or equal to ${data.maximum}.`);
};
if (data.type === 'integer' && input % 1 !== 0) {
errorMessages.push('Value must be an integer.');
}
return { isValid: !errorMessages.length, message: errorMessages.join(' ') };
};

return (
<input
type="text"
className="theia-input"
pattern="[0-9]*"
value={currentValue}
onChange={onChange}
data-preference-id={id}
/>
<div className='pref-input-container'>
<input
type="number"
className="theia-input"
pattern="[0-9]*"
value={currentValue}
onChange={onChange}
onBlur={onBlur}
data-preference-id={id}
/>
{!!validationMessage.length ? <div className='pref-error-notification'>{validationMessage}</div> : undefined}
</div>
);
};

0 comments on commit 928a3bf

Please sign in to comment.