4 weeks ago - last edited 4 weeks ago
If I use a sap.m.Input with type "Number" in combination with valueLiveUpdate="true", and I use a type in my binding, like Float or Decimal, I cannot enter decimal numbers.
When I set my language to French, where the dot "." for decimals is a comma ",", even without the valueLiveUpdate, I does not let me enter decimals
Does anyone know how I can fix this issue? Please check this Plunker with an example: Plunker - SAPUI5: Input type number issues with decimals
<Input type="Number" valueLiveUpdate="true" value="{path:'/value',type: 'sap.ui.model.odata.type.Decimal',constraints:{scale:'variable', minimum: '0'}, formatOptions: {groupingEnabled: false }}"/>
<Input type="Number" valueLiveUpdate="true" value="{path:'/value2',type: 'sap.ui.model.type.Float', constraints: { minimum: 0} ,formatOptions: {groupingEnabled: false }}"/>
Request clarification before answering.
Hello robbewuyts,
I understand the problem. It's tricky to get number input right in SAPUI5, especially when you want to handle decimals and different ways people format numbers around the world. Here's the breakdown:
The Problem
Basically, the standard sap.m.Input control, especially when you set it to type="Number", has some limitations with how it handles decimal points (dots and commas) and the way people group numbers (like 1,234.56 or 1.234,56). This becomes even more complex when you want the input to update your data as the user types (valueLiveUdpate="true").
Here's why it's tricky:
Browser Behavior: The underlying HTML <input type="number"> element behaves differently across browsers and often defaults to expecting a dot (".") as the decimal separator.
Locale Differences: In some countries (like France), a comma (",") is used as the decimal separator, and dots (".") are used for grouping thousands. We need to handle both.
Live Updates: When you update the data with every keystroke, you need to validate partial input, which can be complex with these different formats.
The Solution
The most reliable way to handle this is to take control of the validation yourself. Instead of relying on type="Number", we'll use a combination of:
Allowing Flexible Input: We'll let the user type numbers, dots, and commas freely.
Validating as They Type: We'll use the liveChange event to check the input with each keystroke and provide feedback.
Custom Validation Logic: We'll create a function to make sure the number is in a valid format, considering both decimal separators and grouping.
Here's the code snippet:
onLiveChange: function(oEvent) {
const oSource = oEvent.getSource();
const sValue = oEvent.getParameter("value");
const maxDecimalPlaces = 2;
// 1. Allow only digits, dot, and comma
if (!this._isValidInput(sValue)) {
oSource.setValue(sValue.slice(0, -1)); // Remove invalid char
oSource.setValueState("Error");
oSource.setValueStateText("Numbers, dot, and comma allowed.");
return;
} else {
oSource.setValueState("None"); // Reset error message
}
// 2. Validate the number format (grouping, decimals)
this._validateNumberFormat(oSource, sValue, maxDecimalPlaces);
},
_isValidInput: function(sValue) {
const allowedCharsRegex = /^[\d.,]*$/;
return allowedCharsRegex.test(sValue);
},
_validateNumberFormat: function(oInput, sValue, maxDecimalPlaces) {
// Handle empty input or just a separator
if (sValue === "" || sValue === "." || sValue === ",") {
return;
}
// Determine if the decimal is dot or comma
const decimalSeparator = this._determineDecimalSeparator(sValue);
const parts = sValue.split(decimalSeparator);
let integerPart = parts[0];
let decimalPart = parts[1] || "";
// Determine grouping separators based on decimal separator
const groupingSeparatorsRegex = decimalSeparator === "." ? /,/g : /\./g;
// Validate the integer part (allow grouping separators)
let cleanedIntegerPart = integerPart.replace(groupingSeparatorsRegex, "");
if (!/^\d*$/.test(cleanedIntegerPart)) {
oInput.setValueState("Error");
oInput.setValueStateText("Invalid number format.");
return;
}
// Validate decimal part length
if (maxDecimalPlaces !== undefined && maxDecimalPlaces >= 0 && decimalPart.length > maxDecimalPlaces) {
const truncatedValue = integerPart + decimalSeparator + decimalPart.slice(0, maxDecimalPlaces);
oInput.setValue(truncatedValue); // Truncate decimals
oInput.setValueState("Warning");
oInput.setValueStateText("Max " + maxDecimalPlaces + " decimals.");
return;
}
// Clear warning if it's now valid
if (oInput.getValueState() === "Warning" && oInput.getValueStateText().includes("decimals")) {
oInput.setValueState("None");
oInput.setValueStateText("");
}
},
_determineDecimalSeparator: function(sValue) {
const dotIndex = sValue.lastIndexOf(".");
const commaIndex = sValue.lastIndexOf(",");
if (dotIndex > commaIndex) {
return ".";
} else if (commaIndex > dotIndex) {
return ",";
} else {
return sValue.includes(".") ? "." : sValue.includes(",") ? "," : "."; // Default
}
},
In summary: We're taking control of the input validation to handle different number formats correctly. This gives you the flexibility to support various locales and provide a better user experience. Feel free to modify the code as per your requirement.
I understand it’s a bit complicated, but I hope you find it helpful! I'm also happy to hear any suggestions for improvement, this is the best solution I’ve been able to come up with so far.
GenAI was used to help generate this content.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Farooq,
Please note that according to our Rules of Engagement. "If you want to publish content that was helped/created by GenAI, you must add the user tag GenAI Assisted Content. For content where it's not possible to add a user tag (e.g., answers), you must include this statement: "GenAI was used to help generate this content." We have edited your answer and added the GenAI-statement as we detected AI-generated content in your post. Thank you for your contribution in the SAP Community!
Best Regards
Kavya
User | Count |
---|---|
68 | |
15 | |
12 | |
7 | |
7 | |
4 | |
4 | |
4 | |
4 | |
3 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.