Debounce Help for Database Search--- URGENT

I’ve asked this question a few times and no help. I am looking for some help now. Let me know how to solve this. It is starting to effect user experience so it would be nice to get help fast.
I am trying to get my on key debounce to work in my database search. It doesn’t seem to be working. Here is my code.

import wixData from ‘wix-data’;
//For full API documentation, including code examples visit http://wix.to/94BuAAs
$w.onReady(function () {
//TODO: import wixData from ‘wix-data’;
});
let debounceTimer;
export function iTitle_keyPress(event, $w) {
if (debounceTimer){
clearTimeout (debounceTimer);
debounceTimer = undefined;
}
debounceTimer = setTimeout(()=> {($w(’ #iTitle ‘).value);},200);
wixData.query(‘Business_Directory’)
.contains(‘title’,$w(’ #iTitle ‘).value)
.find()
.then(res => {
$w(’ #repeater1 ‘).data = res.items;
});
}
export function ibusinessCategory1_change(event, $w) {
wixData.query(‘Business_Directory’)
.contains(‘businessCategory1’,$w(’ #ibusinessCategory1 ‘).value)
.find()
.then(res => {
$w(’ #repeater1 ').data = res.items;
});
}

URL is: https://www.sleepyhollowtarrytownchamber.com/business-directory

Hi,
I don’t understand what you are trying to achieve. Can you please clarify? Moreover, I noticed that you set the data to the repeater but you don’t set the information to the repeater elements. I recommend checking out the onItemReady documentation .

Best,
Tal.

Tal,
So the reason my code is the way it is because I followed this tutorial.

There were a lot of issues with this code specifically with the dropdown portion of it so I listed out all the category items in the dropdown list because this code: https://www.wix.com/code/home/forum/advanced-tips-tricks/remove-duplicates-from-connected-dropdown-options
wasn’t working and the video code wasn’t working to load the values of the dropdown as what I needed filtered.
That is why I the data to the repeater but you don’t see the set information to the repeater elements.

However, that is wholly unrelated to my question at hand, as that is the part of code that is working just fine.
In the On Key there should be a debounce because the results are delayed in the typing. If you reference this video: Wix Code | How to Create a Search for Your Database - YouTube
That coding can be found between minute 1:03-3:50.

Despite typing the code as shown in the video there were still issues with what the video describes as the flicker and the reason for the debounce code. I also referenced this code: Totally Codable - Trusted Velo Community

The flicker is still happening. I want to fix that. I am reposting my code and screen shots of how I have everything set up.

import wixData from ‘wix-data’;

$w.onReady( function () {
//TODO: import wixData from ‘wix-data’;
});
let debounceTimer;
export function iTitle_keyPress(event, $w) {
if (debounceTimer){
clearTimeout (debounceTimer);
debounceTimer = undefined;
}
debounceTimer = setTimeout(()=> {($w(‘#iTitle’).value);},500);
wixData.query(‘Business_Directory’)
.contains(‘title’,$w(‘#iTitle’).value)
.find()
.then(res => {
$w(‘#repeater1’).data = res.items;
$w(‘#ibusinessCategory1’).value = undefined;
$w(‘#ibusinessCategory1’).resetValidityIndication();
});
}

export function ibusinessCategory1_change(event, $w) {
wixData.query(‘Business_Directory’)
.contains(‘businessCategory1’,$w(‘#ibusinessCategory1’).value)
.find()
.then(res => {
$w(‘#repeater1’).data = res.items;
});
}

Please actually look at my url and try it. You will see the On Key debounce is not working.

URL: https://www.sleepyhollowtarrytownchamber.com/business-directory

Type in something like bike to see what I mean. Please tell me how to improve this using example code. It is easier for me to visualize.
Thank you

Hi,

The main problem that you have is that you are getting a whole bunch of errors. This will certainly cause problems in the display:

You also haven’t implemented the Repeater’s onItemReady() function. This might be the cause of the errors.

The debounce is also not implemented correctly as you don’t have the database query inside of the setTimeout() . For information on how to use debounce , see the forum post Give the TextInput onKeyPress Function some time .

Yisrael

Please note … The tutorial you refer to uses a filter on the dataset. You have your repeater connected to the dataset, and you are also performing a query on collection and then using the query results to set the Repeater’s data property. This will cause major problems and is probably the main cause of the flickering (and other problems as well).

Yisreal, Thank you for the updates. I realize I am getting an error because not every entry has an image. However, I need the filter to work with the repeater because I have to have a uniform look to the entries even if some fields are missing data. I am open to options, I tabled this for a while because this is was less pressing than I thought. Can anyone help find a way to get this to work? Maybe through hidden elements. It would be easier to see my errors if the correct code was re written and compared with the old one.

Just wanted to check in on this because on my dynamic page I was trying to use a Null error like this to avoid the errors, but it comes up anyway.

$w.onReady( function () {
$w(“#repeater1”).onItemReady( ($w, itemData, index) => {
console.log(itemData.logo);
if (itemData.logo === “null”) {
$w(“#image34”).hide();
} else {
$w(“#image34”).show();
}
});
});

How do I avoid this error if there is no image value?

This is the new code on the non dynamic page by the way

import wixData from ‘wix-data’;
$w.onReady( function () {
//TODO: import wixData from ‘wix-data’;
});
let debounceTimer;
export function iTitle_keyPress(event, $w) {
if (debounceTimer){
clearTimeout (debounceTimer);
debounceTimer = undefined;
}
debounceTimer = setTimeout(()=> {($w(‘#iTitle’).value);},500);
wixData.query(‘BusinessDirectory_New’)
.contains(‘businessName’,$w(‘#iTitle’).value)
.find()
.then(res => {
$w(‘#repeater1’).data = res.items;
$w(‘#ibusinessCategory1’).value = undefined;
$w(‘#ibusinessCategory1’).resetValidityIndication();
});
}

export function ibusinessCategory1_change(event, $w) {
wixData.query(‘BusinessDirectory_New’)
.contains(‘businessCategory1’,$w(‘#ibusinessCategory1’).value)
.find()
.then(res => {
$w(‘#repeater1’).data = res.items;
});
}

null is not a string. Therefore…

Not this:
if(itemData.logo === “null”) {
but this:
if(itemData.logo === null) {

To avoid the problem of flicker, you need to include the query in the setTimeout() function of the debounce code:

let debounceTimer;
export function iTitle_keyPress(event, $w) {
   if (debounceTimer) {
      clearTimeout(debounceTimer);
      debounceTimer = undefined;
   }
   debounceTimer = setTimeout(() => {
      let val = $w('#iTitle').value;
      console.log(val);
      wixData.query('BusinessDirectory_New')
      .contains('businessName', val)
      .find()
      .then(res => {
         $w('#repeater1').data = res.items;
         $w('#ibusinessCategory1').value = undefined;
         $w('#ibusinessCategory1').resetValidityIndication();
      });
   }, 500);
}

Good luck,

Yisrael

Yisrael,
You have been so helpful with this.
It is still not working. The error of the images is still happening.

I am now trying to work backwards.

Remember how you said. “The tutorial you refer to uses a filter on the dataset. You have your repeater connected to the dataset”

I thought that the tutorial also features a repeater. How then is it populating the images? Is there a tutorial for this exact set up somewhere because I have only found things on connecting the data set to the repeater. Especially because without the connection it doesn’t show the data.

Just a reminder of the tutorial so that you don’t have to back track to much.

I like to get this right.

Thank you, again.

The problem isn’t the repeater. It’s that you have the repeater connected to the dataset, and you’re also doing a query and then setting the repeater.data to the results of a query. One will overwrite the other.

I would say that you should either disconnect the repeater from the dataset, or use the dataset to populate the repeater by setting the appropriate filter on the dataset. Using both a dataset and a query creates a conflict.

I completely understand what you mean, but if I don’t attach my data set to the repeater it doesn’t show all the data. I haven’t been able to find a way to show all the data in the data set and disconnect the repeater.
If you look at the repeater example

They use the same database that runs the query. This is where the conflict is.

Do you know if a tutorial for that exists? I don’t believe I can preform the search function without the query. So, I would like a solution for the disconnecting of the repeater.

I found what I was looking for here:

This is my new code:
import wixData from ‘wix-data’;

$w.onReady( function () {
$w(“#repeater1”).onItemReady( ($w, itemData, index) => {
$w(“#businessname”).text = itemData.businessName;
$w(“#subcatdes”).text = itemData.categorySubDescriptor;
$w(“#addline1”).text = itemData.addressLine1;
$w(“#addline2”).text = itemData.addressLine2;
$w(“#citystzip”).text = itemData.cityStateZip;
$w(“#description”).text = itemData.businessDescription;
$w(“#logo”).src = itemData.logo;
} );

wixData.query(‘BusinessDirectory_New’)
.find()
.then( (results) => {
$w(“#repeater1”).data = results.items;
} );
} );

$w.onReady( function () {
//TODO: import wixData from ‘wix-data’;
});
let debounceTimer;
export function iTitle_keyPress(event, $w) {
if (debounceTimer){
clearTimeout (debounceTimer);
debounceTimer = undefined;
}
debounceTimer = setTimeout(()=> {($w(‘#iTitle’).value);},500);
wixData.query(‘BusinessDirectory_New’)
.contains(‘businessName’,$w(‘#iTitle’).value)
.find()
.then(res => {
$w(‘#repeater1’).data = res.items;
$w(‘#ibusinessCategory1’).value = undefined;
$w(‘#ibusinessCategory1’).resetValidityIndication();
});
}

export function ibusinessCategory1_change(event, $w) {
wixData.query(‘BusinessDirectory_New’)
.contains(‘businessCategory1’,$w(‘#ibusinessCategory1’).value)
.find()
.then(res => {
$w(‘#repeater1’).data = res.items;
});
}

$w.onReady( function () {
$w(“#repeater1”).onItemReady( ($w, itemData, index) => {
console.log(itemData.logo);
if (itemData.logo === null ) {
$w(“#logo”).hide();
} else {
$w(“#logo”).show();
}
});
});

$w.onReady( function () {
$w(“#repeater1”).onItemReady( ($w, itemData, index) => {
console.log(itemData.addressLine2);
if (itemData.addressLine2 === null ) {
$w(“#addline2”).hide();
} else {
$w(“#addline2”).show();
}
});
});

$w.onReady( function () {
$w(“#repeater1”).onItemReady( ($w, itemData, index) => {
console.log(itemData.businessDescription);
if (itemData.businessDescription === null ) {
$w(“#description”).hide();
} else {
$w(“#description”).show();
}
});
});

However,
I can tell that the debounce is still not working.
I keep getting this error


even though I have the code to hide the null values.

Also, do you know how to sort the data so it always appears alphabetical based on a certain field?
Thank you again for the help.

Also, why is it taking a bit to load data? I keep seeing my repeater template before the load this is concerning.

I need to be able to link the button in repeater to a dynamic page when I write this it doesn’t work
$w(“#button”). link = ‘https://www.sleepyhollowtarrytownchamber.com/BusinessDirectory-New/profile/{Business Name}’;
What do I have to do to make this work? I have tried with the field key as well neither work.
I don’t want to connect the dataset to the repeater.

Hi Elizabeth:

Some things that you may need to consider here.

You really should only have one $w.onReady() function. If you don’t you will have some bad side effects. So you should consider consolidating the code from the other onReady functions into the same $w.onReady() function call.

Think of onReady as an egg Timer. If you put five eggs into boil you don’t normally have 5 eggTimers running, you have one that tells you that all the eggs are ready. This is essentially what $w.onReady does. It tells you that the site is loaded and ready for display giving you a chance to do a few final things now that all of your elements are available to work with.

The same is true for onItemReady(). This is a function that we call a handler. It handles events from other actions being carried out for you in the background. In this case the repeater is working in the background to build out the repeated components and populating the elements in those components from your dataset along the way. Again, think about my egg timer example, when each component is ready to be added to your page the onItemReady function is called to give you a chance to make last minute changes to each specific item before they are made ready for display.

See if this graphic helps


So in the graphic you will see my attempt to show how and when the onReady functions are used. In the Repeater For loop the data for the Red Item View is processed and the onItemReady() fucntion is called before it is added to the repeater Container. Then the loop continues with the next Item, the Green Item again the item view is built and then the onItemReady() function is called again for the Green Item and so on.

Now one other thing that you really need to do is verify that you are using valid values in your repeater. So for example these errors:


Are actually caused in this part of your code:


So there are empty values in the itemData properties you are trying to assign to the text element. Here is a tip for these types of situation. Use a function helper to validate the data that you want to assign like this:

function assignValidValue(elementName, elementProperty, elementValue) {
    if (elementValue && elementProperty && elementValue) {
        $w(elementName)[elementProperty] = elementValue;
    }
}

Now you can write code like this and not worry about null values. Of course you can make the validator more sophisticated but this should prevent most repeater or other element value assignment errors.

$w.onReady(() => {
    $w('#repeater1').onItemReady( ($w, itemData, index) => {
        assignValidValue('#businessName', 'text', itemData.businessName);
        assignValidValue('#subcatdes'), 'text', itemDataSubCategoryDescriptor);
        ...
        assignValidValue('#addline2', 'text', itemData.addressLine2);
        assignValidValue('#description', 'text', itemData.businessDescription);
        assignValidValue('#logo', 'src', itemData.logo);
    });
});

Hope you find this helpful.

Steve

Steve,
Thank you for such a detailed response. This is really like the best type of answers. I was thinking I needed just one on ready, but no one cited that as the problem. I’ll try this and see how it goes. Do you have any suggestions on how to link my dynamic page to the profile button? Also, do you have a suggestion for alphabetizing the entries based on the Business Name column? For this I am thinking a sort function, but just want to double check.

Elizabeth:

Please check my profile page to see how to connect with me offline. This last question is getting a little too detailed for the forum and is getting into more site design questions.

Thanks

Steve,
I have been working with what you gave me. Here are the results…

Here is the First Code I tried:

import wixData from ‘wix-data’;

export function assignValidValue(elementName, elementProperty, elementValue) {
if (elementValue && elementProperty && elementValue) {
$w(elementName)[elementProperty] = elementValue;
$w.onReady( function () {
$w(“#repeater1”).onItemReady( ($w, itemData, index) => {
$w(“#businessname”).text = itemData.businessName;
$w(“#subcatdes”).text = itemData.categorySubDescriptor;
$w(“#addline1”).text = itemData.addressLine1;
$w(“#addline2”).text = itemData.addressLine2;
$w(“#citystzip”).text = itemData.cityStateZip;
$w(“#description”).text = itemData.businessDescription;
$w(“#logo”).src = itemData.logo;
$w(“#fullprofbutton”).link = ‘https://www.sleepyhollowtarrytownchamber.com/BusinessDirectory-New/profile/(#businessname)’;
if (itemData.title === “NON”) {
$w(“#membadge”).hide();
$w(“#fullprofbutton”).hide();
} else {
$w(“#membadge”).show();
$w(“#fullprofbutton”).show();
}
$w.onReady( function () {
$w(“#repeater1”).onItemReady( ($w, itemData, index) => {
assignValidValue(‘#businessName’, ‘text’, itemData.businessName);
assignValidValue(‘#subcatdes’, ‘text’, itemData.categorySubDescriptor);
assignValidValue(‘#addline2’, ‘text’, itemData.addressLine2);
assignValidValue(‘#description’, ‘text’, itemData.businessDescription);
assignValidValue(‘#logo’, ‘src’, itemData.logo);
$w(“#fullprofbutton”).link = ‘https://www.sleepyhollowtarrytownchamber.com/BusinessDirectory-New/Profile/{businessName}’;
});
wixData.query(‘BusinessDirectory_New’)
.ascending(“Businessname”)
.find()
.then((results) => {
$w(“#repeater1”).data = results.items;
});
let debounceTimer;
function iTitle_keyPress(event, $w) {
if (debounceTimer){
clearTimeout (debounceTimer);
debounceTimer = undefined;
}
debounceTimer = setTimeout(()=>
{($w(‘#iTitle’).value);
},500);
wixData.query(‘Business_Directory’)
.contains(‘title’,$w(‘#iTitle’).value)
.find()
.then(res => {
$w(‘#repeater1’).data = res.items;
});
}
function ibusinessCategory1_change(event, $w) {
wixData.query(‘Business_Directory’)
.contains(‘businessCategory1’, $w(‘#ibusinessCategory1’).value)
.find()
.then(res => {
$w(‘#repeater1’).data = res.items;
});
}

The reason I modified the above code was because I keep getting a parsing error token at the end.

I then tried this code:

import wixData from ‘wix-data’;

$w.onReady( function () {
$w(“#repeater1”).onItemReady( ($w, itemData, index) => {
$w(“#businessname”).text = itemData.businessName;
$w(“#subcatdes”).text = itemData.categorySubDescriptor;
$w(“#addline1”).text = itemData.addressLine1;
$w(“#addline2”).text = itemData.addressLine2;
$w(“#citystzip”).text = itemData.cityStateZip;
$w(“#description”).text = itemData.businessDescription;
$w(“#logo”).src = itemData.logo;
$w(“#fullprofbutton”).link = ‘https://www.sleepyhollowtarrytownchamber.com/BusinessDirectory-New/profile/(#businessname)’;
if (itemData.title === “NON”) {
$w(“#membadge”).hide();
$w(“#fullprofbutton”).hide();
} else {
$w(“#membadge”).show();
$w(“#fullprofbutton”).show();
}
});
});
function assignValidValue(elementName, elementProperty, elementValue) {
$w(“#repeater1”).onItemReady(($w, itemData, index) => {
assignValidValue(‘#businessName’, ‘text’, itemData.businessName);
assignValidValue(‘#subcatdes’, ‘text’, itemData.categorySubDescriptor);
assignValidValue(‘#addline2’, ‘text’, itemData.addressLine2);
assignValidValue(‘#description’, ‘text’, itemData.businessDescription);
assignValidValue(‘#logo’, ‘src’, itemData.logo);
$w(“#fullprofbutton”).link = ‘https://www.sleepyhollowtarrytownchamber.com/BusinessDirectory-New/Profile/{businessName}’;
});
wixData.query(‘BusinessDirectory_New’)
.ascending(“Businessname”)
.find()
.then((results) => {
$w(“#repeater1”).data = results.items;
});
let debounceTimer;
function iTitle_keyPress(event, $w) {
if (debounceTimer){
clearTimeout (debounceTimer);
debounceTimer = undefined;
}
debounceTimer = setTimeout(()=>
{($w(‘#iTitle’).value);
},500);
wixData.query(‘Business_Directory’)
.contains(‘title’,$w(‘#iTitle’).value)
.find()
.then(res => {
$w(‘#repeater1’).data = res.items;
});
}
function ibusinessCategory1_change(event, $w) {
wixData.query(‘Business_Directory’)
.contains(‘businessCategory1’,$w(‘#ibusinessCategory1’).value)
.find()
.then(res => {
$w(‘#repeater1’).data = res.items;
});
}
}

While there were zero alerts to errors when I tried this nothing functioned.

Here is my new code:

import wixData from ‘wix-data’;
//For full API documentation, including code examples visit Velo API Reference - Wix.com
$w.onReady(
function assignValidValue(elementName, elementProperty, elementValue) {
$w(“#repeater1”).onItemReady(($w, itemData, index) => {
assignValidValue(‘#businessName’, ‘text’, itemData.businessName);
assignValidValue(‘#subcatdes’, ‘text’, itemData.categorySubDescriptor);
assignValidValue(‘#addline2’, ‘text’, itemData.addressLine2);
assignValidValue(‘#description’, ‘text’, itemData.businessDescription);
assignValidValue(‘#logo’, ‘src’, itemData.logo);
$w(“#fullprofbutton”).link = ‘https://www.sleepyhollowtarrytownchamber.com/BusinessDirectory-New/Profile/{businessName}’;
console.log(itemData.title);
if (itemData.title === “NON”) {
$w(“#membadge”).hide();
$w(“#fullprofbutton”).hide();
} else {
$w(“#membadge”).show();
$w(“#fullprofbutton”).show();
}
});
wixData.query(‘BusinessDirectory_New’)
.ascending(“Businessname”)
.find()
.then((results) => {
$w(“#repeater1”).data = results.items;
});
let debounceTimer;
function iTitle_keyPress(event, $w) {
if (debounceTimer){
clearTimeout (debounceTimer);
debounceTimer = undefined;
}
debounceTimer = setTimeout(()=>
{($w(‘#iTitle’).value);
},500);
wixData.query(‘Business_Directory’)
.contains(‘title’,$w(‘#iTitle’).value)
.find()
.then(res => {
$w(‘#repeater1’).data = res.items;
});
}
function ibusinessCategory1_change(event, $w) {
wixData.query(‘Business_Directory’)
.contains(‘businessCategory1’,$w(‘#ibusinessCategory1’).value)
.find()
.then(res => {
$w(‘#repeater1’).data = res.items;
});
}
});

I get no code errors until I run a preview. It is saying Maximum Call Stack Size Exceeded.

I think you misunderstood I have theses things designed and created.
As you can see I already implemented the alphabetical sort I was looking for
with: .ascending(“Businessname”) under the query.

I just need a string for my full profile button I was using this
$w(“#fullprofbutton”).link = ’ https://www.sleepyhollowtarrytownchamber.com/BusinessDirectory-New/Profile/{businessName} ';
,but it won’t pull the value. I can reconnect that piece to the repeater if need be, but I was wondering if there was a work around to accomplish zero repeater connections.

If you can help make the best of the 3 I gave it would be helpful.