Input onKeyPress Function Working Only After Clicking Away

I have a form on my website for people to sign up to a newsletter. The form is a single text box field (#input8), to which I have attached a dataset (#dataset2). After a user enters their email, I want them to be able to press the enter key on their keyboard to submit the form. On a successful submission I show a success message (#text37).

The code I have is as follows:
$w.onReady(function () {
$w(“#input8”).onKeyPress((event, $w) => {
if (event.key === “Enter”) {
$w(“#dataset2”).save()
.then( () => {
$w(“#text37”).show(“FadeIn”);
});
}
});
});

What I want is that this code should work as follows:

  1. User types in email into input
  2. User clicks Enter key
    (User’s email is saved to the database)

However, the issue I am having is that this code only works if the user does the following:

  1. User types email into input
  2. User clicks off of input box
  3. User clicks back into input box
  4. User clicks Enter key
    (User’s email is saved to the database)

I am not sure why the onKeyPress seems to only work on the first key press. I expect the onKeyPress to be a binding event that is listening to all key presses in that input box.

Some additional information that may be helpful:

  • The form and database are in the footer of my website
  • The code is set in the site onReady function (not the page onReady function)

Has anyone had a similar issue and found a solution or work around?

Thanks

Not really sure what exactly is going wrong for you, but perhaps the input field is not yet ready to be used by the dataset. You can try a small timeout:

$w("#input8").onKeyPress((event, $w) => {
   console.log("keypress: " + event.key);
   setTimeout(() => {
      if (event.key === "Enter") {
      $w("#dataset2").save()
         .then(() => {
            $w("#text37").show("FadeIn");
          });
      }
   }, 10);
});

I’m really not sure if this will help. Might be worth trying while I shift the brain into high gear and see if I can figure out anything else.

To check if the onKeyPress() event handler is being called or not, I added a console.log() statement.

Yisrael

Hi Yisrael,

Thank you for the advice. I gave the timeout a try and am still experiencing the issue I described both when I preview my website and on the live website.

Let me add a little additional information that may be helpful:

  • The form and database are in the footer of my website
  • The code is set in the site onReady function (not the page onReady function)

(Added to original post as well)

Did you add console.log() ? Is onKeyPress() being triggered for all key presses?

Also, a bit weird that the code is in your site’s onReady() . Seems to me that would cause some confusion. I’m at least confused. :upside_down_face:

Hi Yisrael,

Thanks for the pointers. I have added the console.log() statement and I do see all key presses including the Enter. Adding the logging also uncovered a new error that was not previously not showing in the console:

Uncaught (in promise)
{
code: “DS_VALIDATION_ERROR”,
message: “Some of the elements validation failed”,
name: “DatasetError”,
stack: “DatasetError: Some of the elements validation failed
at l (https://static.parastorage.com/services/dbsm-viewer-app/1.220.0/app.js:1:106793)
at Object.execute [as ADAPTER_API] (https://static.parastorage.com/services/dbsm-viewer-app/1.220.0/app.js:1:107322)
at https://static.parastorage.com/services/dbsm-viewer-app/1.220.0/app.js:6:61643
at f (https://static.parastorage.com/services/dbsm-viewer-app/1.220.0/app.js:1:96873)
at y (https://static.parastorage.com/services/dbsm-viewer-app/1.220.0/app.js:6:61614)
at Array.map () at https://static.parastorage.com/services/dbsm-viewer-app/1.220.0/app.js:6:62376”,
Symbol(error was handled): true
}

Interestingly, when I update my code to catch the error and print it, the error goes away, but the issue remains that my Enter is not triggering the save:

$w.onReady(function () {
$w(“#input8”).onKeyPress((event, $w) => {
console.log(event.key);
if (event.key === “Enter”) {
$w(“#dataset2”).save()
.then( () => {
$w(“#text37”).show(“FadeIn”);
})
.catch( (err) => {
console.log(err);
});
}
});
});

(No output displayed as a result of the catch and logging)

The nature of my problem seems to have changed a little, as there seems to be some underlying dataset error that may be the root cause. However, given the simplicity of my code and form set-up I am at a loss for what the issue could be. To quickly review my additional set up:

  • My database has a single “text” type field (called “email”)
  • My text input has “email” as its type. (I also tried “text” and get the same issue where “Enter” does not work)
  • My text input requires that the field is populated
  • My text input has no pattern validation
  • My text input is connected to my dataset, with the “value connects to” correctly mapped to the column in my database (“email (Text)”)
  • My dataset is in “Write-only” mode

I added the code to the onReady() statement because the WIX API documentation seemed to indicate it is best practice. There is a note regarding the save function that the dataset may not be ready until after the page is fully loaded. (wix-dataset - Velo API Reference - Wix.com).

The issue of the dataset not being ready until after the page is fully loaded really shouldn’t be an issue here since you’re performing an action on the dataset after a keypress. The dataset certainly is ready by then.

The fact that you have your code in the site onReady() gives me pause (for something).

As is stated in the wix-dataset AP I, “A dataset connects page elements to a set of items in a data collection.” Not sure if that means that the code should be on the page as well. Might be worth trying that - maybe we’ll both learn something.

Agree, I don’t think it should be an issue. You make an interesting point about the page vs site. I tried a few things, none of which seems to fix the issue:

  1. Include the code in the page onReady() function only
  2. Include the code in the site and page onReady() functions
  3. Added an onKeyPress: function to the input using the Developer Properties dialog and inserted the save code into that function. (When I do this, the function is added to the site code automatically, not the page code)
  4. Moved the input and dataset into the page and included the code in the page onReady() function
  5. Moved the input and dataset into the page and included the code in an onKeyPress: function added using the Developer Properties dialog (in the page code, not site code)

In every case I see all key presses logged including the Enters. And I also get the same uncaught error whenever I click Enter in each scenario above.

(One other accidental test I did is I disconnected the input form from the dataset. In this scenario pressing Enter in the input box after typing the email works every time. The dataset also saves every time, except that it saves a blank entry because the input is not connected.)

Finally one other thing I tested is I removed the “required” setting from the input box. When I remove this setting, pressing Enter triggers the save behavior, but for some reason the database saves a blank entry. (I confirmed that the input and dataset were connected for this test.)

Just to be clear, the error I previously pasted about the uncaught promise seems to be triggered based upon whether I have the “required” setting enabled. It seems that i must click off of the field for the field to validate that a value has been provided, and that is why I get the validation error. (Not sure if that is a bug or intended behavior.) However, it seems that there is an additional issue where the value of the field is not picked up by the dataset unless the field is marked as required. (Again, possibly a bug, but not sure what the intended behavior should be.)

I am going to try a work around to make #input8 not “required”, and then in the code I will try to insert the value from the field directly into the database using the setFieldValue method of #dataset2.

Let me know if you think that approach would work?

Seems to me that your problem is the Uncaught (in promise) error. Especially after having disconnected the dataset, the problem seems to be revolving around this issue.

If you don’t make any headway, please post the URL of your site. Only authorized Wix personnel can get access to your site in the editor. Let me know on what page the problem occurs.

Good luck!

Hi Yisrael,

I agree with your assessment. And as I discovered, the Uncaught (in promise) error is related to the required flag on the input box. But also as I pointed out, removing it causes a different breakage.

I have updated my input box to not be “required”, and updated my code to set the value before saving (in the onReady() function of the site). This results in the desired behavior. My code now looks like:

$w.onReady(function () {
$w(“#input8”).onKeyPress((event, $w) => {
if (event.key === “Enter”) {
$w(“#dataset2”).setFieldValue(“email”, $w(“#input8”).value);
$w(“#dataset2”).save()
.then( () => {
$w(“#text37”).show(“FadeIn”);
});
}
});
});

For future reference to others or WIX developers, this code works around two issues that I believe are bugs:

  1. A form input field with the “required” setting enabled will not validate whether it has input (and therefore meets the “required” state) until after a user has clicked off of the input field.

  2. On a single input form that does not have a submit button (and relies on a key press to submit the data from the input), the dataset will not capture the information from the input field unless it is marked as “required” in the input field settings. This may also apply more generally to forms with multiple inputs, or forms with submit buttons, but I did not test the behaviors for these scenarios.

1 Like

Edited my response above. I have resolved the issue by working around the two bugs I encountered and saving the value from the input directly to the dataset.

I also hav a problem with keyPress events. If I console log the value of the Input Field it is always missing the last entered character. How come?

Hey Andreas,

You need to use debounce…

let debounceTimer;
export function input1_keyPress(event, $w) {
   if (debounceTimer) {
      clearTimeout(debounceTimer);
      debounceTimer = undefined;
   }
   debounceTimer = setTimeout(() => {
      let val = $w('#input1').value;
      console.log(val); 
   }, 500);
}

or a simple timeout…

export function input1_keyPress(event, $w) { 
   setTimeout(() => {
      let val = $w('#input1').value;
      console.log(val); 
   }, 10);
}

The debounce is more “robust” and is good to use in auto complete type functions where the user might type too fast causing code execution problems.

I hope this helps.

Yisrael

2 Likes

Thanks a lot. This is article material :slight_smile:

1 Like

Andreas, just for you…
Give the TextInput onKeyPress Function some time
:smiling_face:

This is nearly a year late but I want to say THANK YOU.

I built an autocomplete address input and without this debounce, it was all sorts of wacky.

Thanks again!