I have a repeater on a dynamic (all) page. Each item in the repeater has a button that connects to a URL field in the collection. Some items don’t have URL’s, so I am disabling the button with this code:
import wixData from 'wix-data';
$w.onReady(function () {
function disableButtons() {
$w("#dataset1").onReady( () => {
$w("#repeater1").forEachItem( ($item, itemData) => {
if (itemData.manualUrl === undefined){
$item("#manualButton").disable()
}
} );
} );
}
disableButtons()
} );
The function works fine, but the problem is when I filter the dataset using a dropdown. I followed this tutorial and the filtering also works fine. I’m just having trouble getting the two pieces to work together. It will keep the correct buttons disabled the first time filtering with the dropdown, but on the second time, all of the buttons are enabled.
Things I’ve tried:
-
Running disableButtons()
inside of anonChange()
on the dropdownn.
-
Running disableButtons()
inside of a onCurrentIndexChanged()
on the dataset.
Any ideas how to make this work?
import wixData from 'wix-data';
$w.onReady(function () {
function disableButtons() {
$w("#dataset1").onReady( () => {
$w("#repeater1").forEachItem( ($item, itemData) => {
if (itemData.manualUrl === undefined){
$item("#manualButton").disable()
}
} );
} );
}
disableButtons() //<--- WHAT IS THIS?
} );
You surely have more code, which you do not mention here!
That’s not the best idea! When you awaiting some good output, you also have to make some good input ! ! !
What does do your “disableButtons()”- function ?
function disableButtons() { ???????????????????? }
$w.onReady(function () {
function disableButtons() {
$w("#dataset1").onReady( () => {
$w("#repeater1").forEachItem( ($item, itemData) => {
if (itemData.manualUrl === undefined){
$item("#manualButton").disable()
}
else {$item("#manualButton").enable()}
} );
} );
}
} );
Edit:
Ok, i saw it, sorry!
$w.onReady(function () { disableButtons() })
function disableButtons() {
$w("#dataset1").onReady( () => {
$w("#repeater1").forEachItem( ($item, itemData) => {
if (itemData.manualUrl === undefined){
$item("#manualButton").disable()
}
else {$item("#manualButton").enable()}
} );
} );
}
Look directly above where it says disableButtons() in the code…
Yes already did ^^ (better version)
$w.onReady(function () {
$w("#dataset1").onReady( () => {
$w("#repeater1").forEachItem( ($item, itemData) => {
if (itemData.manualUrl === undefined){
$item("#manualButton").disable()
}
else {$item("#manualButton").enable()}
});
});
});
Thanks for the help. Same results with your code. On the second time filtering all of the buttons are enabled.
When all buttons are enabled on the second time?
What could this make happen ?
—> undefined - values on the second search-round ???
I don’t know all your code and what is behind the scenes, perhaps there are also other elements or code-parts which causes the issue.
I don’t know because i can not see it.
You can try to make some console-logs!
$w.onReady(function () {
$w("#dataset1").onReady( () => {
$w("#repeater1").forEachItem( ($item, itemData) => {
console.log(itemData.manualUrl)
if (itemData.manualUrl === undefined){console.log("undefined")
$item("#manualButton").disable()
}
else {$item("#manualButton").enable(), console.log("URL-found")}
});
});
});
@russian-dima I tried that too. It doesn’t log after the first page load. I think the key is getting the function to run after the filter, but I’m not really sure what’s going on behind the scenes with the dropdown filter.
I made a mock site in case anyone want to play around with it, but I’m not sure how to share and let the code be seen and manipulated.
$w("#dropdown1").onChange( () => {
setTimeout(function(){
disableButtons()
}, 2000);
} );
Adding a delay after the dropdown filters the repeater seems to work on the 2nd+ filter. Not ideal so open to other options. I’m sure I’m missing something.
Final code as of now:
$w.onReady(function () {
$w("#dataset1").onReady( () => {
disableButtons()
$w("#dropdown1").onChange( () => {
setTimeout(function(){
disableButtons()
}, 2000);
} );
function disableButtons() {
$w("#repeater1").forEachItem( ($item, itemData) => {
if (itemData.manualUrl === undefined){
$item("#manualButton").disable();
console.log("undefined")
} else {
console.log("URL found")
}
} );
}
} )
} );
BTW, even without the delay, the console logs in disableButtons() show the correct information for each button, but it logs the previous state of the visible repeater items.
Ok, now i think i understand the issue, or better said, i assume to understand the issue. I will take a look…
@russian-dima https://wix.to/AMBKDBM this might help give you a visual.
$w.onReady(function () { //<---PAGE = READY (o.k.)
$w("#dataset1").onReady( () => { //<---dataset = READY (o.k.)
//disableButtons() //<-- ????????????????
$w("#dropdown1").onChange(() => {//<-- first action (o.k.)
setTimeout(function(){
disableButtons()
}, 100);
} );
function disableButtons() {
$w("#repeater1").forEachItem(async($item, itemData) => {
let xxx = await itemData.manualUrl
if (xxx === undefined){
$item("#manualButton").disable();
console.log("undefined")
} else {
console.log("URL found")
}
} );
}
} )
} );
Does this work ?
@russian-dima Nope
This is what happens, it:
- disables the correct buttons of the CURRENT items in the repeater
- filters the repeater
- shows new repeater with all buttons enabled.
//disableButtons() //<-- ???
This first disableButtons() call that you are putting “???” next to disables the buttons on page load.
I think you’re on the right track with async await. I’ll see if I can get it to work using that. In the meantime, here is an updated site where you can set the delay and also see the buttons change before the filter happens.
https://wix.to/E8BYDBM
edit: fixed link
Ok i did not see that you already change the code a little bit…
My question is why you try to start a function in an already running event?
//STEP-I: --------------------------
$w.onReady(function() {
$w("#dataset1").onReady(() => {
$w("#repeater1").onReady(() => {
$w("#dropdown1").onChange(() => {
});
});
});
});
//STEP-II:---------------------------
$w.onReady(function() {
$w("#dataset1").onReady(() => {
$w("#repeater1").onReady(() => {
$w("#dropdown1").onChange(() => {
$w("#repeater1").forEachItem(async($item, itemData) => {
})
});
});
});
});
//STEP-III:---------------------------
$w.onReady(function() {
$w("#dataset1").onReady(() => {
$w("#repeater1").onReady(() => {
$w("#dropdown1").onChange(() => {
$w("#repeater1").forEachItem(async($item, itemData) => {
await $item("#manualButton").disable();
if (itemData.manualUrl !== undefined){
$item("#manualButton").enable();
}
})
});
});
});
});
OR…
//STEP-III:---------------------------
$w.onReady(function() {
$w("#dataset1").onReady(() => {
$w("#dropdown1").onChange(() => {
$w("#repeater1").onReady(() => {
$w("#repeater1").forEachItem(async($item, itemData) => {
await $item("#manualButton").disable();
if (itemData.manualUrl !== undefined){
$item("#manualButton").enable();
}
})
});
});
});
});
Thanks, but this doesn’t work.
“My question is why you try to start a function in an already running event?”
I’m running the function when the page loads, and when the dropdown changes.
Code with comments:
$w.onReady(function () { // wait for page to be ready
$w("#dataset1").onReady( () => { // wait for dataset to be ready
// run disableButtons() function when page loads and dataset is ready (see function below)
disableButtons()
// run disableButton() when dropdown filter is used
$w("#dropdown1").onChange( () => {
disableButtons()
} );
// function that disables buttons
function disableButtons() {
$w("#repeater1").forEachItem( ($item, itemData) => { // for each item in repeater...
if (itemData.manualUrl === undefined){ // check if manualUrl field is undefined
$item("#manualButton").disable(); // if undefined, disable button
}
} );
}
} )
} );
edit: removed setTimeout code for clarity
Here’s the best answer I could come up with. It bypasses filtering the content by dropdown , and uses filter() , onChange() , and then().
import wixData from 'wix-data';
$w.onReady(function () { // wait for page to be ready
$w("#dataset1").onReady( () => { // wait for dataset to be ready
// run disableButtons() function when page loads and dataset is ready (see function below)
disableButtons()
// run disableButton() when dropdown filter is used
$w("#dropdown1").onChange( () => {
let dropdownVal = $w("#dropdown1").value
$w("#dataset1").setFilter( wixData.filter()
.eq("color", dropdownVal)
).then( () => {
disableButtons()
} );
} );
// function that disables buttons
function disableButtons() {
$w("#repeater1").forEachItem( ($item, itemData) => { // for each item in repeater...
if (itemData.manualUrl === undefined){ // check if manualUrl field is undefined
$item("#manualButton").disable(); // if undefined, disable button
}
} );
}
} );
} );
It’s still a bit slower than I’d prefer, but it does the job.