Hey Everyone,
I am hoping to get help with optimizing my code. I have multiple reference fields that are connected to 10 difference repeaters. Each one acts as a submission/dynamic form which a user signs up and fills out and then can go back and update.
I have a lot of redundant code (wixData.isReferenced, and wixData.queryReferenced) which is calling the network multiple times and is slowing down the page.
NOTE: it is important that the checkboxes be either inserted or replaced as they may be blank to start.
Additionally, the code doesn't seem to capture all the checkboxes when selected. Let's say I check every item displayed in the repeater and save, only maybe 1/3 or half of them get saved in the collection
Anyone have suggestions on how to optimize/improve?
$w.onReady(() => { $w("#dynamicDataset").onReady(() => { $w.onReady(function () { wixData.query("Members") .eq("_owner", wixUsers.currentUser.id) .find() .then((results4) => { let OwnerRegistered = results4.items; let MemberID = OwnerRegistered[0]._id; let MemberOwner = OwnerRegistered[0]._owner; let Profile = $w("#dynamicDataset").getCurrentItem(); let ProfileID = Profile._id; $w("#DecorRepeater").forEachItem(($item, itemData, index) => { let DecorCheckbox = $item("#checkbox405"); let DecorID = itemData._id wixData.isReferenced("DesignProfile", "items", ProfileID, DecorID).then((result3) => { let isReferenced3 = result3; if (isReferenced3 === true) { DecorCheckbox.checked = true } else { DecorCheckbox.checked = false } }) wixData.queryReferenced("DesignProfile", ProfileID, "items") .then((results11) => { if (results11.items.length > 0) { ///ON SAVE - REPLACE REFERENCES/// $w('#SaveProfile').onClick((event, $w) => { let checked = []; if (DecorCheckbox.checked) checked.push(DecorID); wixData.replaceReferences("DesignProfile", "items", ProfileID, checked) .then(() => { }) .catch((error) => { }); }); } else { //ON SAVE - INSERT REFERENCES//// $w('#SaveProfile').onClick((event, $w) => { let checked = []; if (DecorCheckbox.checked) checked.push(DecorID); wixData.insertReference("DesignProfile", "items", ProfileID, checked) .then(() => { }) }) } }); }); $w("#RoomRepeater").forEachItem(($item, itemData, index) => { let RoomsCheckbox = $item("#checkbox406"); let RoomsID = itemData._id wixData.isReferenced("DesignProfile", "rooms", ProfileID, RoomsID).then((result3) => { let isReferenced3 = result3; if (isReferenced3 === true) { RoomsCheckbox.checked = true } else { RoomsCheckbox.checked = false } }) wixData.queryReferenced("DesignProfile", ProfileID, "rooms") .then((results11) => { if (results11.items.length > 0) { ///ON SAVE - REPLACE REFERENCES/// $w('#SaveProfile').onClick((event, $w) => { let checked = []; if (RoomsCheckbox.checked) checked.push(RoomsID); wixData.replaceReferences("DesignProfile", "rooms", ProfileID, checked) .then(() => { }) .catch((error) => { }); }); } else { //ON SAVE - INSERT REFERENCES//// $w('#SaveProfile').onClick((event, $w) => { let checked = []; if (RoomsCheckbox.checked) checked.push(RoomsID); wixData.insertReference("DesignProfile", "rooms", ProfileID, checked) .then(() => { }) }) } }); }); $w("#StyleRepeater").forEachItem(($item, itemData, index) => { let StyleCheckbox = $item("#checkbox407"); let StyleID = itemData._id wixData.isReferenced("DesignProfile", "style", ProfileID, StyleID).then((result3) => { let isReferenced3 = result3; if (isReferenced3 === true) { StyleCheckbox.checked = true } else { StyleCheckbox.checked = false } }) wixData.queryReferenced("DesignProfile", ProfileID, "style") .then((results11) => { if (results11.items.length > 0) { ///ON SAVE - REPLACE REFERENCES/// $w('#SaveProfile').onClick((event, $w) => { let checked = []; if (StyleCheckbox.checked) checked.push(StyleID); wixData.replaceReferences("DesignProfile", "style", ProfileID, checked) .then(() => { }) .catch((error) => { }); }); } else { //ON SAVE - INSERT REFERENCES//// $w('#SaveProfile').onClick((event, $w) => { let checked = []; if (StyleCheckbox.checked) checked.push(StyleID); wixData.insertReference("DesignProfile", "style", ProfileID, checked) .then(() => { }) }) } }); }); $w("#VibeRepeater").forEachItem(($item, itemData, index) => { let VibeCheckbox = $item("#checkbox408"); let VibeID = itemData._id wixData.isReferenced("DesignProfile", "vibe", ProfileID, VibeID).then((result3) => { let isReferenced3 = result3; if (isReferenced3 === true) { VibeCheckbox.checked = true } else { VibeCheckbox.checked = false } }) wixData.queryReferenced("DesignProfile", ProfileID, "vibe") .then((results11) => { if (results11.items.length > 0) { ///ON SAVE - REPLACE REFERENCES/// $w('#SaveProfile').onClick((event, $w) => { let checked = []; if (VibeCheckbox.checked) checked.push(VibeID); wixData.replaceReferences("DesignProfile", "vibe", ProfileID, checked) .then(() => { }) .catch((error) => { }); }); } else { //ON SAVE - INSERT REFERENCES//// $w('#SaveProfile').onClick((event, $w) => { let checked = []; if (VibeCheckbox.checked) checked.push(VibeID); wixData.insertReference("DesignProfile", "vibe", ProfileID, checked) .then(() => { }) }) } }); }); $w("#PriorityRepeater").forEachItem(($item, itemData, index) => { let PrioritiesCheckbox = $item("#checkbox409"); let PrioritiesID = itemData._id wixData.isReferenced("DesignProfile", "priorities", ProfileID, PrioritiesID).then((result3) => { let isReferenced3 = result3; if (isReferenced3 === true) { PrioritiesCheckbox.checked = true } else { PrioritiesCheckbox.checked = false } }) wixData.queryReferenced("DesignProfile", ProfileID, "priorities") .then((results11) => { if (results11.items.length > 0) { ///ON SAVE - REPLACE REFERENCES/// $w('#SaveProfile').onClick((event, $w) => { let checked = []; if (PrioritiesCheckbox.checked) checked.push(PrioritiesID); wixData.replaceReferences("DesignProfile", "priorities", ProfileID, checked) .then(() => { }) .catch((error) => { }); }); } else { //ON SAVE - INSERT REFERENCES//// $w('#SaveProfile').onClick((event, $w) => { let checked = []; if (PrioritiesCheckbox.checked) checked.push(PrioritiesID); wixData.insertReference("DesignProfile", "priorities", ProfileID, checked) .then(() => { }) }) } }); }); $w("#BaseColorRepeater").forEachItem(($item, itemData, index) => { let BaseColorCheckbox = $item("#checkbox403"); let BaseColorID = itemData._id wixData.isReferenced("DesignProfile", "baseColors", ProfileID, BaseColorID).then((result3) => { let isReferenced3 = result3; if (isReferenced3 === true) { BaseColorCheckbox.checked = true } else { BaseColorCheckbox.checked = false } }) wixData.queryReferenced("DesignProfile", ProfileID, "baseColors") .then((results11) => { if (results11.items.length > 0) { ///ON SAVE - REPLACE REFERENCES/// $w('#SaveProfile').onClick((event, $w) => { let checked = []; if (BaseColorCheckbox.checked) checked.push(BaseColorID); wixData.replaceReferences("DesignProfile", "baseColors", ProfileID, checked) .then(() => { }) .catch((error) => { }); }); } else { //ON SAVE - INSERT REFERENCES//// $w('#SaveProfile').onClick((event, $w) => { let checked = []; if (BaseColorCheckbox.checked) checked.push(BaseColorID); wixData.insertReference("DesignProfile", "baseColors", ProfileID, checked) .then(() => { }) }) } }); }); $w("#AccentColorRepeater").forEachItem(($item, itemData, index) => { let AccentColorCheckbox = $item("#checkbox404"); let AccentColorID = itemData._id wixData.isReferenced("DesignProfile", "accentColors", ProfileID, AccentColorID).then((result3) => { let isReferenced3 = result3; if (isReferenced3 === true) { AccentColorCheckbox.checked = true } else { AccentColorCheckbox.checked = false } }) wixData.queryReferenced("DesignProfile", ProfileID, "accentColors") .then((results12) => { if (results12.items.length > 0) { ///ON SAVE - REPLACE REFERENCES/// $w('#SaveProfile').onClick((event, $w) => { let checked = []; if (AccentColorCheckbox.checked) checked.push(AccentColorID); wixData.replaceReferences("DesignProfile", "accentColors", ProfileID, checked) .then(() => { }) .catch((error) => { }); }); } else { //ON SAVE - INSERT REFERENCES//// $w('#SaveProfile').onClick((event, $w) => { let checked = []; if (AccentColorCheckbox.checked) checked.push(AccentColorID); wixData.insertReference("DesignProfile", "accentColors", ProfileID, checked) .then(() => { }) }) } }); }); $w("#MaterialsRepeater").forEachItem(($item, itemData, index) => { let MaterialsColorCheckbox = $item("#checkbox411"); let MaterialsColorID = itemData._id wixData.isReferenced("DesignProfile", "materials", ProfileID, MaterialsColorID).then((result3) => { let isReferenced3 = result3; if (isReferenced3 === true) { MaterialsColorCheckbox.checked = true } else { MaterialsColorCheckbox.checked = false } }) wixData.queryReferenced("DesignProfile", ProfileID, "materials") .then((results12) => { if (results12.items.length > 0) { ///ON SAVE - REPLACE REFERENCES/// $w('#SaveProfile').onClick((event, $w) => { let checked = []; if (MaterialsColorCheckbox.checked) checked.push(MaterialsColorID); wixData.replaceReferences("DesignProfile", "materials", ProfileID, checked) .then(() => { }) .catch((error) => { }); }); } else { //ON SAVE - INSERT REFERENCES//// $w('#SaveProfile').onClick((event, $w) => { let checked = []; if (MaterialsColorCheckbox.checked) checked.push(MaterialsColorID); wixData.insertReference("DesignProfile", "materials", ProfileID, checked) .then(() => { }) }) } }); }); $w("#PatternsRepeater").forEachItem(($item, itemData, index) => { let PatternsColorCheckbox = $item("#checkbox410"); let PatternsColorID = itemData._id wixData.isReferenced("DesignProfile", "patterns", ProfileID, PatternsColorID).then((result3) => { let isReferenced3 = result3; if (isReferenced3 === true) { PatternsColorCheckbox.checked = true } else { PatternsColorCheckbox.checked = false } }) wixData.queryReferenced("DesignProfile", ProfileID, "patterns") .then((results12) => { if (results12.items.length > 0) { ///ON SAVE - REPLACE REFERENCES/// $w('#SaveProfile').onClick((event, $w) => { let checked = []; if (PatternsColorCheckbox.checked) checked.push(PatternsColorID); wixData.replaceReferences("DesignProfile", "patterns", ProfileID, checked) .then(() => { }) .catch((error) => { }); }); } else { //ON SAVE - INSERT REFERENCES//// $w('#SaveProfile').onClick((event, $w) => { let checked = []; if (PatternsColorCheckbox.checked) checked.push(PatternsColorID); wixData.insertReference("DesignProfile", "patterns", ProfileID, checked) .then(() => { }) }) } }); }); $w("#WhyHomeWellRepeater").forEachItem(($item, itemData, index) => { let WhyColorCheckbox = $item("#checkbox413"); let WhyColorID = itemData._id wixData.isReferenced("Members", "whyHomeWell", MemberID, WhyColorID).then((result3) => { let isReferenced3 = result3; if (isReferenced3 === true) { WhyColorCheckbox.checked = true } else { WhyColorCheckbox.checked = false } }) wixData.queryReferenced("Members", MemberID, "whyHomeWell") .then((results12) => { if (results12.items.length > 0) { ///ON SAVE - REPLACE REFERENCES/// $w('#SaveProfile').onClick((event, $w) => { let checked = []; if (WhyColorCheckbox.checked) checked.push(WhyColorID); wixData.replaceReferences("Members", "whyHomeWell", MemberID, checked) .then(() => { }) .catch((error) => { }); }); } else { //ON SAVE - INSERT REFERENCES//// $w('#SaveProfile').onClick((event, $w) => { let checked = []; if (WhyColorCheckbox.checked) checked.push(WhyColorID); wixData.insertReference("Members", "whyHomeWell", MemberID, checked) .then(() => { }) }) } }); }); $w("#SaveProfile").onClick((event, $w) => { $w("#SaveProfile").disable() wixLocation.to('/MyAccount/Home/' + MemberID) }); }); }); }); });
@stcroppe @Liran Kurtz (WIX) @Sapir (wix) @Jenee Washington @Yisrael (Wix) @Yoav (Wix) @Mike Moynihan
[@Tarra Maxwell] Tarra can you share the published page that your code is on? Context is important to considering your question. Cheers
@stcroppe thanks for reaching out! This is a dynamic membership page. Please go to: https://www.dohomewell.com/ and signup - it will be "DESIGN PROFILE" link in your member toolbar header.
All - here are some screenshots of the form - each question/section is a different repeater which pulls items for 10 different collections (rooms, items, colors, etc)
@Tarra Maxwell Hi Tarra: That helped with context. What you need to do is something called refactoring. To refactor the code you pull out anything that seems to be repeated into a function. Then use that function where the repeated code is. You adjust the way the function behaves by passing arguments that define the differences. I have refactored your code to show you a way to do this. I haven't tested it so Caveat Emptor ;-) Hopefully you should be able to understand what I have done based on the comments I have added.
import wixLocation from 'wix-location'; import wixWindow from "wix-window"; import wixData from 'wix-data'; import wixUsers from 'wix-users'; let user = wixUsers.currentUser; let userId = user.id; let isLoggedIn = user.loggedIn; // Generic collapseFold() function used to collapse a fold with a given index function collapseFold(index) { $w('#fold' + index).collapse(); $w('#arrowDown' + index).hide(); $w('#arrowUp' + index).show(); $w('#headBox' + index).style.backgroundColor = "#FFFFFF"; } // Generic expandFold() function used to expand a fold with a given index function expandFold(index) { $w('#fold' + index).expand(); $w('#arrowDown' + index).show(); $w('#arrowUp' + index).hide(); $w('#headBox' + index).style.backgroundColor = "#CCEAEA"; } // Loops through each fold index // if the index argument matches then the fold is expanded // other wise it is collapsed. function toggleFold(index) { // update the folds [2, 3, 4, 5, 6, 7].forEach(idx => { // If the index matches the idx in our list we expand the fold // Otherwise we collapse it if (index === idx) { // Match - expand the fold using our generic expand fucntion expandFold(idx); } else { // No Match - collapse the fold using our generic collapse fucntion collapseFold(idx); } }); } // Generic function that extracts the fold number from the clicked on target elementID // With this value it calls toggle fold to update the UI export function headBoxEvent(event) { // Get the target element id let id = event.target.id; // This should be headBox<number> let foldIndex = Number(id.replace("headBox", "")); toggleFold(foldIndex); } // All fold click handlers use the same event handler // The event handler figures out which fold was clicked before // Toggling them accordingly // NOTE: the property dialogue boxes that are bound to these click functions could all // be connected directly to the headBoxEvent function and all of these _click functions // can then be deleted export function headBox2_click(event) { headBoxEvent(event); } export function headBox3_click(event) { headBoxEvent(event); } export function headBox4_click(event) { headBoxEvent(event); } export function headBox5_click(event) { headBoxEvent(event); } export function headBox6_click(event) { headBoxEvent(event); } export function headBox7_click(event) { headBoxEvent(event); } $w.onReady(() => { $w("#dynamicDataset").onReady(() => { $w.onReady(function () { wixData.query("Members") .eq("_owner", wixUsers.currentUser.id) .find() .then((results4) => { let OwnerRegistered = results4.items; let MemberID = OwnerRegistered[0]._id; let MemberOwner = OwnerRegistered[0]._owner; let Profile = $w("#dynamicDataset").getCurrentItem(); let ProfileID = Profile._id; // Use a generic repeater function to load the information repeaters updateRepeaterElementWithCheckboxElement("DesignProfile", $w("#DecorRepeater"), "#checkbox405", "items", ProfileId); updateRepeaterElementWithCheckboxElement("DesignProfile", $w("#RoomRepeater"), "#checkbox406", "rooms", ProfileId); updateRepeaterElementWithCheckboxElement("DesignProfile", $w("#StyleRepeater"), "#checkbox407", "style", ProfileId); updateRepeaterElementWithCheckboxElement("DesignProfile", $w("#VibeRepeater"), "#checkbox408", "vibe", ProfileId); updateRepeaterElementWithCheckboxElement("DesignProfile", $w("#PriorityRepeater"), "#checkbox409", "priorities", ProfileId); updateRepeaterElementWithCheckboxElement("DesignProfile", $w("#BaseColorRepeater"), "#checkbox403", "baseColors", ProfileId); updateRepeaterElementWithCheckboxElement("DesignProfile", $w("#AccentColorRepeater"), "#checkbox404", "accentColors", ProfileId); updateRepeaterElementWithCheckboxElement("DesignProfile", $w("#MaterialsRepeater"), "#checkbox411", "materials", ProfileId); updateRepeaterElementWithCheckboxElement("Members", $w("#WhyHomeWellRepeater"), "#checkbox413", "whyHomeWell", MemberId); $w("#SaveProfile").onClick((event, $w) => { $w("#SaveProfile").disable(); wixLocation.to('/MyAccount/Home/' + MemberID); }); }); }); // Generic Repeater handler function. Will load the repeater element passed as an argument based on the value of the other arguments function updateRepeaterElementWithCheckboxElement(dataCollection, repeaterElement, checkBoxId, referenceItem, profileId) { // Make sure we have defined values to work with if (dataCollection && repeaterElement && checkBoxId && referenceItem && profileId) { repeaterElement.forEachItem(($item, itemData, index) => { let Checkbox = $item(checkBoxId); let ItemID = itemData._id; wixData.isReferenced(dataCollection, referenceItem, profileId, ItemID).then((result3) => { let isReferenced3 = result3; if (isReferenced3 === true) { Checkbox.checked = true; } else { Checkbox.checked = false; } }); wixData.queryReferenced(dataCollection, profileId, referenceItem) .then((results11) => { if (results11.items.length > 0) { ///ON SAVE - REPLACE REFERENCES/// $w('#SaveProfile').onClick((event, $w) => { let checked = []; if (Checkbox.checked) { checked.push(ItemID); } wixData.replaceReferences(dataCollection, referenceItem, profileId, checked) .then(() => { }) .catch((error) => { }); }); } else { //ON SAVE - INSERT REFERENCES//// $w('#SaveProfile').onClick((event, $w) => { let checked = []; if (Checkbox.checked) { checked.push(ItemID); } wixData.insertReference(dataCollection, referenceItem, profileId, checked) .then(() => { }); }); } }); }); } else { // May want to do other error handling here console.log("updateRepeaterElementWithCheckboxElement: missing a value!"); } } Hope this helps! Cheers Steve
@Steven Cropper Steve thank you so much I really appreciate it! The code still functions the way i need it to in theory, however the page still takes a lot of time to load and still isn't capturing all the checks properly. For example, i filled out every single checkbox and saved - but only about a 3rd registered and inserted into the collection - any suggestions?
@Tarra Maxwell HI there - well you have a lot going on Tarra and you have several code design challenges that go beyond the refactoring question ;-)
One area that is likely to be an issue is the way you are configuring the saveProfile handler. I helped another user with a misunderstanding over what the onXXX functions actually do. They do not execute the code you write they merely register the code for execution upon some event.
For example this code:
$w('#SaveProfile').onClick((event, $w) => { let checked = []; // <<<<<<<<<NOTE THIS ONLY EVER HAS ONE ITEM ADDED TO IT if (Checkbox.checked) { | checked.push(ItemID); // <<<<<<<<<<<--------------------+ } // If the reference already exists this may fail wixData.insertReference(dataCollection, referenceItem, profileId, checked) .then(() => { }); });
is NOT executed where you declare it. What it does is define a handler that gets called when the button with the ID "SaveProfile" is clicked. Now you have two places where you give a handler to call when this event is detected. This handler is essentially replaced every time the code is called as the repeater is built. This happens ten times over. So which handler is being set?
Again as you will see there is a lot of duplicated code with the minor exception of the use of insertReference instead of updateReference. So an opportunity to refactor the code exists. This is where you should ask yourself "what is the one thing I want SaveProfile to do when it is clicked?". Then write a single function that does what you need and don't embed it inside of a database action result :-). Handlers should ONLY be defined once, either as standalone functions hooked into the element using the property panel, OR in the $w.onReady() function as an onXXX function.
Lastly it seems that what you are trying to do is collect multiple reference items into an array called checked and save the collected items when the button is clicked? This is not what will happen. The checked array does not persist outside of the event handler. So you are only ever putting one value into the array not a collection as you might be expecting. That value is dependent on several other conditions earlier in your code and user behavior.
If you think you would benefit from my help (either to fix the code for you OR in a one-on-one code surgery online) drop me a chat message.
Cheers
Steve