Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Additional validation for integers #3

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@elsci-io/ui-essential",
"version": "1.0.56",
"version": "1.0.57",
"description": "Material Design components created for products built by elsci.io",
"main": "src/index.js",
"type": "module",
Expand Down
4 changes: 4 additions & 0 deletions src/EditText/EditText.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,9 @@ export default class EditText extends HTMLElement {
let patternAttr = "";
if (this.hasAttribute("pattern"))
patternAttr = `pattern="${this.getAttribute("pattern")}"`
let numberTypeAttr = "";
if (this.hasAttribute("number-type"))
numberTypeAttr = `number-type="${this.getAttribute("number-type")}"`
return `<span class="edit-text__text"></span>
<dialog class="edit-text__popup" tabindex="9">
<text-input
Expand All @@ -247,6 +250,7 @@ export default class EditText extends HTMLElement {
${minLengthAttr}
${maxLengthAttr}
${patternAttr}
${numberTypeAttr}
type="${typeAttr}"
></text-input>
</dialog>`;
Expand Down
38 changes: 33 additions & 5 deletions src/TextInput/TextInputValidityState.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,10 @@ export default class TextInputValidityState {
{badInput, customError, patternMismatch, typeMismatch, valid, rangeOverflow, rangeUnderflow, tooLong,
tooShort, valueMissing, stepMismatch},
this.#isBlanknessConstraintViolated(),
this.#isRangeConstraintViolated()
this.#isRangeConstraintViolated(),
this.#isStepConstraintViolated()
);
cv.valid = !cv.valueMissing && !cv.rangeUnderflow && !cv.rangeOverflow;
cv.valid = !cv.valueMissing && !cv.rangeUnderflow && !cv.rangeOverflow && !cv.stepMismatch;
return cv;
}

Expand All @@ -82,14 +83,41 @@ export default class TextInputValidityState {
return {rangeUnderflow: (min !== "" && +value < +min), rangeOverflow: (max !== "" && +value > +max)};
}

/**
* This method serves to supplement internal validation to determine whether a float qualifies as an integer.
* The internal validation for an input type="number" step="1" doesn't consistently cover all cases.
* For example, the number 2.00000001 might be considered an integer by the internal validator.
* So we are using attribute 'number-type="integer"'
* The aim is to widen this validation range. Now, the comparison for an integer works correctly when a number
* has no more than 16 digits. However, if a number has 17 digits or more, this function returns incorrect result.
* @return {{stepMismatch: boolean}}
*/
#isStepConstraintViolated() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Step can exist even if we expect numbers with decimal point. I don't think we can add this validation "by default" if the step is specified.

Instead I'd create an implementation of the validator (what you call an "external" validator at the moment) and place it inside ui-essentials. And then the client code may decide to add it as a validator. It's just in this case the client code won't have to create its own implementation - it already exists in the ui-essential.

if (this.#inputElement.type !== "number")
return {stepMismatch: false};
const numberType = this.#textInput.getAttribute('number-type');
if (!numberType || numberType !== "integer")
return {stepMismatch: false};
const stepMismatch = !Number.isInteger(this.#inputElement.valueAsNumber);
return {stepMismatch: stepMismatch};
}

#getValidationMessage(validityState) {
const isTypeNumber = this.#inputElement.type === "number";
const {badInput, rangeOverflow, rangeUnderflow, tooLong, tooShort, valueMissing, stepMismatch} = validityState;
if (isTypeNumber && badInput)
return "Invalid number";
if (isTypeNumber && stepMismatch && this.#inputElement.step === "1") {
// Here we validate only floats because if step is 1, then the value must be an integer.
return "Must be an integer";
if (isTypeNumber && stepMismatch) {
if (this.#inputElement.step === "1" ){
// Here we checked floats because if step is 1, then the value must be an integer.
// Now we can use attribute 'number-type="integer"', but we have previously written inputs,
// that's why don't want to remove this code
return "Must be an integer";
}
const numberType = this.#textInput.getAttribute('number-type');
if (numberType || numberType === "integer") {
return "Must be an integer";
}
}
if (rangeOverflow)
return "Greater than " + this.#inputElement.max;
Expand Down
Loading