I want to notify my users with a custom alert when they try to paste in characters exceeding the maximum length of the input field.
Acceptance criteria:
What I have tried is js code: (function() { var maxLength = $parameters.MaxLength; // Set your max length here document.addEventListener('keydown', function(event) { // Check if Ctrl+V was pressed if (event.ctrlKey && (event.key === 'v' || event.key === 'V')) { // Wait for the paste event document.addEventListener('paste', function(pasteEvent) { // Get the pasted data var pasteData = (pasteEvent.clipboardData || window.clipboardData).getData('text'); // Check the length of the pasted data if (pasteData.length > maxLength) { $parameters.IsValidPaste = true; // Set the output parameter to true } else { $parameters.IsValidPaste = false; // Set the output parameter to false } }, { once: true }); // Add the paste event listener only once return $parameters.IsValidPaste; } });})();
These are my parameters: It appears that my output parameter never changes to true, even when a user tries to paste data that exceeds the maximum length. Can anyone help me solve this issue?
Hey there,
I think the problem comes from Javascript's asynchronous handling of events. Javascript will execute the "return $parameters.IsValidPaste;" statement first. This means that the initial value is returned, before the event logic was finished.
I recreated this problem of yours in my own personal environment. This is how I managed to trigger a change in the return value in Outsystems depending on the user's input length
// function for keydown event that returns promise whether input longer or less than max length async function checkPastedData(maxLength) { return new Promise((resolve, reject) => { const inputField = document.getElementById("inputField"); inputField.addEventListener('keydown', function(event) { if (event.ctrlKey && (event.key === 'v' || event.key === 'V')) { inputField.addEventListener('paste', function(pasteEvent) { var pasteData = (pasteEvent.clipboardData || window.clipboardData).getData('text'); var isLonger = pasteData.length > maxLength; resolve(isLonger); }); } }); }); }
// main function that sets isLonger and calls other client action with updated value async function main() { var isLonger = await checkPastedData($parameters.maxLength); if (isLonger) { console.log("Pasted data exceeds the maximum length."); //call other client action with updated value $actions.PrintResult(true); } else { console.log("Pasted data is within the allowed length."); //call other client action with updated value $actions.PrintResult(false); } } main();
For me this worked fine by calling the Javascript above from the onKeyDown event handler of the input field.
Hope this works for you as well and excuse the Javascript formatting. I could not make it look prettier.
Hi @Yalda Akhgar,
Firstly, your Output parameter name is IsValidPaste but in your code you written IsLonger, I couldn't see this (IsLonger ) output parameter in JS Node .
Could you please Check your code.
Kind regards,
Sanjay Kushwah
@Sanjay Kushwah sorry, I pasted wrong screenshoot. The code is correct. I think the issue is the output param being updated before the listener updates the parameter
Is your Code is running onONKeyPress Event Handler of your input field.?
I have tried it with onKeydown, onKeypress, onFocus, and onBlur
Hi @Yalda Akhgar, Actually the problem is here, when handler runs the code is defining (your function and adding event Listener before the JS done your handler End.
Hence your Event Listener has been added there but not running that code actually.
The code should be run in next paste, but it will not before again onONKeyPress Event Handler (outsystems handler) will run and again whole function in JS code will define again.
and the process is going on so on.
Code (function) is only defining not running actually.
If you want to make your code work.
Use OnReady Action of your SCREEN/BLOCK to define whole JS Code and For Assinging Output parameter.
Make a separate screen action which will take a input parameter boolean type and will show the custom error message
now call this action into your JS Code.
for Example
el.addEventListener('keypress',function(){
//your js code here//
//store true / false value into a local variable inside js.
// isvalidate=false; (forexample)
$Action.yourSCreenACtionWithInputparam(isvalidate); // pass that value in action which return the same
// when action will fire base on its input (passing from this js code) you can show your custom error message
});
Hope this will help you.
Hey, @Yalda Akhgar
document.addEventListener("DOMContentLoaded", function () {
const inputField = document.querySelector("[name='InputField']");
const alertMessage = document.querySelector("[name='AlertMessage']");
inputField.addEventListener("paste", handlePaste);
inputField.addEventListener("focus", handleFocus);
function handlePaste(event) {
event.preventDefault();
navigator.clipboard.readText().then(text => {
const maxLength = inputField.maxLength;
if (text.length > maxLength) {
alertMessage.innerHTML = `You cannot paste more than ${maxLength} characters.`;
alertMessage.style.display = "block";
} else {
inputField.value = text.substring(0, maxLength);
alertMessage.style.display = "none";
}
function handleFocus() {
alertMessage.innerHTML = `Clipboard data exceeds the maximum length of ${maxLength} characters.`;
I'm just sharing this with you to help you,
thanks
@Vaishali Bhatt I tried the solution you linked. Removing the max length property from the input field allows users to input more than they are allowed, which is not what we want. Our application has auto-save functionality, so doing this could lead to database errors.
Hi Yalda,
For your use case, you can use the JavaScript snippet below to register the paste event handler for the input widget in the OnReady screen event handler flow using the JS element.
JS Snippet:
var inputElement = document.getElementById($parameters.InputId); const maxLength = 10; // Set your desired length limit inputElement.addEventListener('paste', function(event) { const pastedText = event.clipboardData.getData('text'); // Check if pasted text exceeds the max length if (pastedText.length > maxLength) { event.preventDefault(); $actions.CustomFeedbackMsg(`The text you are trying to paste exceeds the maximum length of ${maxLength} characters.`); } });
Demo App: InputPasteEventDemo
Refer to the attached oml
Benjith Sam