-
Notifications
You must be signed in to change notification settings - Fork 77
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(input, input-number, input-text, text-area): ensure all applicabl…
…e props are considered in form validation (#8655) **Related Issue:** #8647 ## Summary This ensures `pattern`, `minlength`, `maxlength`, `min`, `max`, `step` are set on the internal form input based on the matching type. **Note**: `minlength` and `maxlength` won't trigger constraint validation unless a user interacts with the input (see [`minlength` spec](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#setting-minimum-input-length-requirements:-the-minlength-attribute:~:text=Constraint%20validation%3A%20If%20an%20element%20has%20a%20minimum,element%20is%20suffering%20from%20being%20too%20short.) and [`maxlength` spec](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#setting-minimum-input-length-requirements:-the-minlength-attribute:~:text=Constraint%20validation%3A%20If%20an%20element%20has%20a%20maximum,element%20is%20suffering%20from%20being%20too%20long.)). This will have to be a known limitation until #8126 is completed.
- Loading branch information
Showing
11 changed files
with
236 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
38 changes: 38 additions & 0 deletions
38
packages/calcite-components/src/components/input/common/input.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
/* eslint-disable jest/no-conditional-expect -- Using conditional logic in a confined test helper to handle specific scenarios, reducing duplication, balancing test readability and maintainability. **/ | ||
import { minMaxLengthTypes, minMaxStepTypes, patternTypes, syncHiddenFormInput } from "./input"; | ||
|
||
describe("common input utils", () => { | ||
it("syncHiddenFormInput", async () => { | ||
const minMaxLengthTestValues = { minLength: 0, maxLength: 10 }; | ||
const patternTestValue = { pattern: "test" }; | ||
const minMaxStepTestValues = { min: 0, max: 10, step: 1 }; | ||
|
||
const allTypes = Array.from(new Set([...minMaxLengthTypes, ...patternTypes, ...minMaxStepTypes])); | ||
const allValueFakeInputComponent = { ...minMaxLengthTestValues, ...minMaxStepTestValues, ...patternTestValue }; | ||
|
||
const hiddenFormInput = document.createElement("input"); | ||
|
||
allTypes.forEach((type) => { | ||
syncHiddenFormInput(type, allValueFakeInputComponent, hiddenFormInput); | ||
|
||
const expectedType = type === "textarea" ? "text" : type; | ||
|
||
expect(hiddenFormInput.type).toBe(expectedType); | ||
|
||
if (minMaxStepTypes.includes(type)) { | ||
expect(hiddenFormInput.min).toBe("0"); | ||
expect(hiddenFormInput.max).toBe("10"); | ||
expect(hiddenFormInput.step).toBe("1"); | ||
} | ||
|
||
if (minMaxLengthTypes.includes(type)) { | ||
expect(hiddenFormInput.minLength).toBe(0); | ||
expect(hiddenFormInput.maxLength).toBe(10); | ||
} | ||
|
||
if (patternTypes.includes(type)) { | ||
expect(hiddenFormInput.pattern).toBe("test"); | ||
} | ||
}); | ||
}); | ||
}); |
80 changes: 80 additions & 0 deletions
80
packages/calcite-components/src/components/input/common/input.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
export type InputComponent = NumericInputComponent | TextualInputComponent; | ||
|
||
export interface NumericInputComponent { | ||
min: number; | ||
max: number; | ||
step: number | "any"; | ||
} | ||
|
||
export interface TextualInputComponent { | ||
pattern?: string; | ||
minLength: number; | ||
maxLength: number; | ||
} | ||
|
||
/** | ||
* Exported for testing purposes only | ||
*/ | ||
export const minMaxStepTypes = ["date", "datetime-local", "month", "number", "range", "time", "week"]; | ||
|
||
/** | ||
* Exported for testing purposes only | ||
*/ | ||
export const patternTypes = ["email", "password", "search", "tel", "text", "url"]; | ||
|
||
/** | ||
* Exported for testing purposes only | ||
*/ | ||
export const minMaxLengthTypes = ["email", "password", "search", "tel", "text", "textarea", "url"]; | ||
|
||
function updateConstraintValidation( | ||
inputComponent: InputComponent, | ||
input: HTMLInputElement, | ||
propName: string, | ||
matchesType: boolean, | ||
): void { | ||
const attributeName = propName.toLowerCase(); | ||
const value = inputComponent[propName]; | ||
|
||
if (matchesType && value != null) { | ||
input.setAttribute(attributeName, `${value}`); | ||
} else { | ||
// we remove the attribute to ensure validation-constraints are properly reset | ||
input.removeAttribute(attributeName); | ||
} | ||
} | ||
|
||
/** | ||
* Synchronizes the hidden form input with the validation-related input properties. | ||
* | ||
* Note: loss of precision is expected due to the hidden input's value and validation-constraint props being strings. | ||
* | ||
* @param type - The input type. | ||
* @param inputComponent | ||
* @param hiddenFormInput | ||
*/ | ||
export function syncHiddenFormInput( | ||
type: HTMLInputElement["type"] | "textarea", | ||
inputComponent: InputComponent, | ||
hiddenFormInput: HTMLInputElement, | ||
): void { | ||
hiddenFormInput.type = type === "textarea" ? "text" : type; | ||
|
||
const isMinMaxStepType = minMaxStepTypes.includes(type); | ||
const numericInputComponent = inputComponent as NumericInputComponent; | ||
|
||
updateConstraintValidation(numericInputComponent, hiddenFormInput, "min", isMinMaxStepType); | ||
updateConstraintValidation(numericInputComponent, hiddenFormInput, "max", isMinMaxStepType); | ||
updateConstraintValidation(numericInputComponent, hiddenFormInput, "step", isMinMaxStepType); | ||
|
||
const isMinMaxLengthType = minMaxLengthTypes.includes(type); | ||
|
||
const textualInputComponent = inputComponent as TextualInputComponent; | ||
|
||
updateConstraintValidation(textualInputComponent, hiddenFormInput, "minLength", isMinMaxLengthType); | ||
updateConstraintValidation(textualInputComponent, hiddenFormInput, "maxLength", isMinMaxLengthType); | ||
|
||
const isPatternType = patternTypes.includes(type); | ||
|
||
updateConstraintValidation(textualInputComponent, hiddenFormInput, "pattern", isPatternType); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.