Code Review Friday: (Let's Improve your code, ask Corvid Master)

April 24, 2020

Join this week CODE REVIEW organized by Corvid Master,
Comment your code below(as per instruction), we will analyse , give you suggestions,
refactor code that will be easy to read, potential future modifications and plenty of good practices.
We also welcome experienced corvid forum member to share their knowledge and expertise!

Instructions:

  1. What type of code review do you want?(R equired )
  • Refactoring : Want the code to be more readable and scalable?

  • Performance : Want to improve the performance?

  • Discussion : About database structure, page structure and other corvid tools .

  1. Kindly include database structure, collection name & field type (if you refer them in the code).
  2. Is this a live site? If so, send us the link.
  3. Videos or images for explanation are always welcome.
  4. Feel free to paste your code in gist or jsfiddle and share the link on your comment.

Don’ts :

  1. Do NOT include any sensitive code (like passwords, secretkey).
// try to rewrite it as xxxx if it's used inside the code
const key = "XXXX-XXXX";

Note:
We do Code Review EVERY FRIDAY(Pacific Time)!
This post will locked after 24 hours.

2 Likes

Hello, I am trying to add the “All” option into my dropdown connected to a repeater

Today my filter is coded as follows

What should I write to update the export function accordingly. I understand it should be something like this but I don’t manage to include into my codes.

Thank you for your help
Mikael

Moreover, the “All” option appears at the bottom of my dropdown. How can I move it to the top?

Thanks!
Mikael

Here my entire page code:

import wixData from ‘wix-data’ ;
let filter = wixData.filter();

$w.onReady( function () {
uniqueDropdown2();
uniqueDropdown3();

for ( let i = 0 ; i < 3 ; i++) {
filter.filterTree.$and[i] = {}
}

});

function uniqueDropdown2() {
wixData.query( “LinePlan” )
.ascending( “minutesTexts” )
.limit( 1000 )
.find()
.then(results => {
const uniqueTitles = getUniqueTitles(results.items);
let single = buildOptions(uniqueTitles);
single.push({ “label” : “All” , “value” : “All” })
$w( “#dropdown2” ).options = single;
});

function getUniqueTitles(items) {
const titlesOnly = items.map(item => item.minutesTexts);
return [… new Set(titlesOnly)];
}

function buildOptions(uniqueList) {
return uniqueList.map(curr => {
return { label: curr, value: curr };
});
}
}

function uniqueDropdown3() {
wixData.query( “LinePlan” )
.ascending( “data1” )
.limit( 1000 ) //max 1000 per Wix
.find()
.then(results => {
const uniqueTitles = getUniqueTitles(results.items);
let single = buildOptions(uniqueTitles);
single.push({ “label” : “All” , “value” : “All” })
$w( “#dropdown3” ).options = single;
});

function getUniqueTitles(items) {
const titlesOnly = items.map(item => item.data1);
return [… new Set(titlesOnly)];
}

function buildOptions(uniqueList) {
return uniqueList.map(curr => {
return { label: curr, value: curr };
});
}
}

export function dropdown2_change(event, $w) {
let sort = $w( “#dropdown2” ).value;

if ($w( ‘#dropdown2’ ).value.length === 0 ) {
filter.filterTree.$and[ 0 ] = {}
} else {
filter.filterTree.$and[ 0 ] = { “minutesTexts” : $w( ‘#dropdown2’ ).value }; //dropdown element
}
if ($w( ‘#dropdown3’ ).value.length === 0 ) {
filter.filterTree.$and[ 1 ] = {}
} else {
filter.filterTree.$and[ 1 ] = { “data1” : $w( ‘#dropdown3’ ).value }; //dropdown element
}

//filter.filterTree.$and[7] = { “monthly1”: { $lte: String($w(‘#slider1’).value ) } }; //slider element - ‘to’
//console.log(filter)
$w( ‘#dataset1’ ).setFilter(filter).then(() => {
//
})
}

export function dropdown3_change(event) {
let sort = $w( “#dropdown2” ).value;

if ($w( ‘#dropdown2’ ).value.length === 0 ) {
filter.filterTree.$and[ 0 ] = {}
} else {
filter.filterTree.$and[ 0 ] = { “minutesTexts” : $w( ‘#dropdown2’ ).value }; //dropdown element
}
if ($w( ‘#dropdown3’ ).value.length === 0 ) {
filter.filterTree.$and[ 1 ] = {}
} else {
filter.filterTree.$and[ 1 ] = { “data1” : $w( ‘#dropdown3’ ).value }; //dropdown element
}

//filter.filterTree.$and[7] = { “monthly1”: { $lte: String($w(‘#slider1’).value ) } }; //slider element - ‘to’
//console.log(filter)
$w( ‘#dataset1’ ).setFilter(filter).then(() => {
//
})

}

That was fast

suggestion
use a propert id for e.g:
dropdown2 => dropMinutes
dropdown3 => dropData1

import wixData from "wix-data";

$w.onReady(()=>{
 // run 'initFilter' on dropdown changes
 $w('#dropMinutes, #dropData1').onChange(initFilter);
 // run 'initFilter' on button click
 $w('#btnSearch').onClick(initFilter);
});

// filter the dataset based on the input changes
async function initFilter() {
 // save the filter in a variable
 // we will update thie variable
 // based on user inputs
 let filter = wixData.filter();

 // get all the values from selectors and store it in a const
 const dropMinutes = $w('#dropMinutes').value;
 const dropData1 = $w('#dropData1').value;
 const searchbar = $w('#searchbar').value;

 // check if there is a dropdown value and the value is not all
 // if it's true it will update the filter
 // run the eq operation and modify the filter variable
 if(dropMinutes && dropMinutes!=="all") {
 filter = filter.eq("minutesText", dropMinutes);
  }

 // check if there is a dropdown value and the value is not all
 // if it's true it will update the filter
 // run the eq operation and modify the filter variable
 if(dropData1 && dropData1 !=="all") {
 filter = filter.eq("data1", dropData1 );
  }
 // check if there is a input value and the value is not "Any"
 // if it's true it will update the filter
 // run the contains operation and modify the filter variable
 if(searchbar && searchbar !== "Any") {
 filter = filter.contains("aboutMe", dropMinutes);

  }

 // filter the dataset with the filter options builded
 // await for the dataset to be filter
 // before running the next line
 await $w('#dataset1').setFilter(filter);

 // after the dataset is filter getting the total records
 // and saving it in the 'ttl' variable
 let ttl = $w('#dataset1').getTotalCount();

 console.log(`dataset filtered total found : ${ttl}`)
}

Hi, Im trying to add a button to remove a logged in users inputted data from the dsataset without removing other users data. I believe I have to get the filtered data first then bulk remove …I have this code.
It runs without error but does not remove anything…any help would be great thanks.

var array = ;

export function dataset1_ready() {
let count = $w( “#dataset1” ).getTotalCount();

$w( “#dataset1” ).getItems( 0 , count)
.then((res) => {
let items = res.items;
items.forEach((item) => {
array.push(item._id);
});
});
}
export function button3_click(event) {
wixData.bulkRemove( “Membersordersheet” , array)
.then( (results) => {
console.log(results);
})
. catch ( (err) => {
console.log(err);
});

}

Personally i would write it using a query and for loop


async function clearUserData(){

    var d = await wixData.query("collection")
            .eq("_owner",wixUser.currentUser.id)
            .find()
        
    if(d.length > 0){
        var items = d.items
        var bulkRemove = []

        for(var i = 0; i > items.length; i++)
            bulkRemove.push(items[i])
        }

        await wixData
                .bulkRemove("collection", bulkRemove)
        console.log("Items Removed")
    }
}


OK Thank you , Ill give that a try

Full code filter + dropdown options



import wixData from 'wix-data';

$w.onReady(function () {

 // Update UI
 // build dropdown options from the databases
 buildDropOptions("LinePlan", "minutesTexts", "dropMinutes");
 buildDropOptions("LinePlan", "data1", "dropData1");

 // Handle events
 // run 'initFilter' on dropdown changes
 $w('#dropMinutes, #dropData1').onChange(initFilter);
 // run 'initFilter' on button click
 $w('#btnSearch').onClick(initFilter);

});

async function buildDropOptions(collectionName, fieldkey, dropId) {
 if(!collectionName) throw new Error("Collection Name is required!");
 if(!fieldkey) throw new Error("fieldkey is required!");
 if(!dropId) throw new Error("dropdown id is required!");

 // remove dublicate value in an object
 const removeDublicate = items => [...new Set(items.map(item => item[fieldkey]))];
 // conver array into dropdoptions ["foo"] => [{label: "foo", value:"foo"}]
 const buildOptions = _ => _.map(curr =>({ label: curr, value: curr }));
 
 // fetch the data from the database
 const res = wixData.query(collectionName)
    .ascending(sortField)
    .limit(1000)
    .find()

 const title = removeDublicate(res.items);
 let opts = buildOptions(title);
 opts.unshift({"label": "All", "value": "All"})
 $w("#"+dropId).options = opts;
}


// filter the dataset based on the input changes
async function initFilter() {
 // save the filter in a variable
 // we will update thie variable
 // based on user inputs
 let filter = wixData.filter();

 // get all the values from selectors and store it in a const
 const dropMinutes = $w('#dropMinutes').value;
 const dropData1 = $w('#dropData1').value;
 const searchbar = $w('#searchbar').value;

 // check if there is a dropdown value and the value is not all
 // if it's true it will update the filter
 // run the eq operation and modify the filter variable
 if(dropMinutes && dropMinutes!=="all") {
 filter = filter.eq("minutesText", dropMinutes);
  }

 // check if there is a dropdown value and the value is not all
 // if it's true it will update the filter
 // run the eq operation and modify the filter variable
 if(dropData1 && dropData1 !=="all") {
 filter = filter.eq("data1", dropData1 );
  }
 // check if there is a input value and the value is not "Any"
 // if it's true it will update the filter
 // run the contains operation and modify the filter variable
 if(searchbar && searchbar !== "Any") {
 filter = filter.contains("aboutMe", dropMinutes);

  }

 // filter the dataset with the filter options builded
 // await for the dataset to be filter
 // before running the next line
 await $w('#dataset1').setFilter(filter);

 // after the dataset is filter getting the total records
 // and saving it in the 'ttl' variable
 let ttl = $w('#dataset1').getTotalCount();

 console.log(`dataset filtered total found : ${ttl}`)
}


@salman-hammed Thanks for your reply.
Actually, this is the results I got

Certainly, I have not written the code properly:

import wixData from “wix-data” ;

$w.onReady(()=>{
// run ‘initFilter’ on dropdown changes
$w( ‘#dropdown2, #dropdown3’ ).onChange(initFilter);
// run ‘initFilter’ on button click
});

// filter the dataset based on the input changes
async function initFilter() {
// save the filter in a variable
// we will update thie variable
// based on user inputs
let filter = wixData.filter();

// get all the values from selectors and store it in a const
const dropdown2 = $w( ‘#dropdown2’ ).value;
const dropdown3 = $w( ‘#dropdown3’ ).value;

function uniqueDropdown2() {
wixData.query( “LinePlan” )
.ascending( “minutesTexts” )
.limit( 1000 )
.find()
.then(results => {
const uniqueTitles = getUniqueTitles(results.items);
let single = buildOptions(uniqueTitles);
single.push({ “label” : “All” , “value” : “All” })
$w( “#dropdown2” ).options = single;
});

function getUniqueTitles(items) {
const titlesOnly = items.map(item => item.minutesTexts);
return [… new Set(titlesOnly)];
}

function buildOptions(uniqueList) {
return uniqueList.map(curr => {
return { label: curr, value: curr };
});
}
}

function uniqueDropdown3() {
wixData.query( “LinePlan” )
.ascending( “data1” )
.limit( 1000 ) //max 1000 per Wix
.find()
.then(results => {
const uniqueTitles = getUniqueTitles(results.items);
let single = buildOptions(uniqueTitles);
single.push({ “label” : “All” , “value” : “All” })
$w( “#dropdown3” ).options = single;
});

function getUniqueTitles(items) {
const titlesOnly = items.map(item => item.data1);
return [… new Set(titlesOnly)];
}

function buildOptions(uniqueList) {
return uniqueList.map(curr => {
return { label: curr, value: curr };
});
}
}

// check if there is a dropdown value and the value is not all
// if it’s true it will update the filter
// run the eq operation and modify the filter variable
if (dropdown2 && dropdown2!== “all” ) {
filter = filter.eq( “minutesTexts” , dropdown2);
}

// check if there is a dropdown value and the value is not all
// if it’s true it will update the filter
// run the eq operation and modify the filter variable
if (dropdown3 &dropdown3 !== “all” ) {
filter = filter.eq( “data1” , dropdown3 );
}
// check if there is a input value and the value is not “Any”
// if it’s true it will update the filter
// run the contains operation and modify the filter variable

// filter the dataset with the filter options builded
// await for the dataset to be filter
// before running the next line
await $w( ‘#dataset1’ ).setFilter(filter);

// after the dataset is filter getting the total records
// and saving it in the ‘ttl’ variable
let ttl = $w( ‘#dataset1’ ).getTotalCount();

console.log(dataset filtered total found : ${ttl})
}

@mikael Check my last full code i sent you and also make sure to rename your dropdown ids

@salman-hammed
Should I duplicate this part for each dropdown with filters?

async function buildDropOptions ( collectionName , fieldkey , dropId ) {
if ( ! collectionName ) throw new Error ( “Collection Name is required!” );
if ( ! fieldkey ) throw new Error ( “fieldkey is required!” );
if ( ! dropId ) throw new Error ( “dropdown id is required!” );

// conver array into dropdoptions [“foo”] => [{label: “foo”, value:“foo”}]
const buildOptions = _ => _ . map ( curr => ({ label : curr , value : curr }));

// fetch the data from the database
const res = wixData . query ( collectionName )
. distinct ( fieldkey ) // remove dublications
. ascending ( fieldkey )
. find ()
. limit ( 1000 )

let title = res . items . map ( item => item [ fieldkey ]);
title . unshift ( “All” );
$w ( “#” + dropId ). options = buildOptions ( title );
}

Mikael,

one note. Try to avoid using filterTree property. It’s not part of public API and could be removed in newer versions of the Wix Data client library.

@salman-hammed
I still have the same results. Should I input anything in the Property Panel for the drops?

Here the codes
import wixData from ‘wix-data’ ;

$w.onReady( function () {

// Update UI
// build dropdown options from the databases
buildDropOptions( “LinePlan” , “minutesTexts” , “dropMinutes” );
buildDropOptions2( “LinePlan” , “data1” , “dropData1” );

// Handle events
// run ‘initFilter’ on dropdown changes
$w( ‘#dropMinutes, #dropData1’ ).onChange(initFilter);
// run ‘initFilter’ on button click

});

async function buildDropOptions(LinePlan, minutesTexts, dropMinutes) {
if (!LinePlan) throw new Error( “Collection Name is required!” );
if (!minutesTexts) throw new Error( “fieldkey is required!” );
if (!dropMinutes) throw new Error( “dropdown id is required!” );

// conver array into dropdoptions [“foo”] => [{label: “foo”, value:“foo”}]
const buildOptions = _ => _.map(curr => ({ label: curr, value: curr }));

// fetch the data from the database
const res = wixData.query(LinePlan)
.distinct(minutesTexts) // remove dublications
.ascending(minutesTexts)
.find()
.limit( 1000 )

let title = res.items.map(item => item[minutesTexts]);
title.unshift( “All” );
$w( “#dropMinutes” ).options = buildOptions(title);
}

async function buildDropOptions2(LinePlan, data1, dropData1) {
if (!LinePlan) throw new Error( “Collection Name is required!” );
if (!data1) throw new Error( “fieldkey is required!” );
if (!dropData1) throw new Error( “dropdown id is required!” );

// conver array into dropdoptions [“foo”] => [{label: “foo”, value:“foo”}]
const buildOptions = _ => _.map(curr => ({ label: curr, value: curr }));

// fetch the data from the database
const res = wixData.query(LinePlan)
.distinct(data1) // remove dublications
.ascending(data1)
.find()
.limit( 1000 )

let title = res.items.map(item => item[data1]);
title.unshift( “All” );
$w( “#dropData1” ).options = buildOptions(title);
}

// filter the dataset based on the input changes
async function initFilter() {
// save the filter in a variable
// we will update thie variable
// based on user inputs
let filter = wixData.filter();

// get all the values from selectors and store it in a const
const dropMinutes = $w( ‘#dropMinutes’ ).value;
const dropData1 = $w( ‘#dropData1’ ).value;

// check if there is a dropdown value and the value is not all
// if it’s true it will update the filter
// run the eq operation and modify the filter variable
if (dropMinutes && dropMinutes !== “all” ) {
filter = filter.eq( “minutesText” , dropMinutes);
}

// check if there is a dropdown value and the value is not all
// if it’s true it will update the filter
// run the eq operation and modify the filter variable
if (dropData1 && dropData1 !== “all” ) {
filter = filter.eq( “data1” , dropData1);

// check if there is a input value and the value is not “Any”
// if it’s true it will update the filter
// run the contains operation and modify the filter variable

}

// filter the dataset with the filter options builded
// await for the dataset to be filter
// before running the next line
await $w( ‘#dataset1’ ).setFilter(filter);

// after the dataset is filter getting the total records
// and saving it in the ‘ttl’ variable
let ttl = $w( ‘#dataset1’ ).getTotalCount();

console.log(dataset filtered total found : ${ttl})
}

Many thanks!

@mikael Does the code worked before?
Do u have the live site if so paste it here? It will help to debug
Use the code i gave without any modifications and publish it
I will check it live and let you know
Double check the fields key and collections

@salman-hammed
Yes the codes worked before but drops
1/ didn’t contain “All type”
2/ were filtered separately. I wanted to set up conditional filtering between the 2 drops.
Here the URL https://www.issoyopro.com/copy-of-mobile-fr-line-plan
Fields key and collection name are correct.
Many thanks

@mikael try this
don’t modify the code
we can reuse the same buildDropFunction it will take lot less code


import wixData from 'wix-data';

$w.onReady(function () {

 // Update UI
 // build dropdown options from the databases
 buildDropOptions("LinePlan", "minutesTexts", "dropMinutes");
 buildDropOptions("LinePlan", "data1", "dropData1");

 // Handle events
 // run 'initFilter' on dropdown changes
 $w('#dropMinutes, #dropData1').onChange(initFilter);
 // run 'initFilter' on button click
 $w('#btnSearch').onClick(initFilter);

});

async function buildDropOptions(collectionName, fieldkey, dropId) {
 if(!collectionName) throw new Error("Collection Name is required!");
 if(!fieldkey) throw new Error("fieldkey is required!");
 if(!dropId) throw new Error("dropdown id is required!");

 // remove dublicate value in an object
 const removeDublicate = items => [...new Set(items.map(item => item[fieldkey]))];
 // conver array into dropdoptions ["foo"] => [{label: "foo", value:"foo"}]
 const buildOptions = _ => _.map(curr =>({ label: curr, value: curr }));
 
 // fetch the data from the database
 const res = wixData.query(collectionName)
    .ascending(sortField)
    .limit(1000)
    .find()

 const title = removeDublicate(res.items);
 let opts = buildOptions(title);
 opts.unshift({"label": "All", "value": "All"})
 $w("#"+dropId).options = opts;
}


// filter the dataset based on the input changes
async function initFilter() {
 // save the filter in a variable
 // we will update thie variable
 // based on user inputs
 let filter = wixData.filter();

 // get all the values from selectors and store it in a const
 const dropMinutes = $w('#dropMinutes').value;
 const dropData1 = $w('#dropData1').value;
 const searchbar = $w('#searchbar').value;

 // check if there is a dropdown value and the value is not all
 // if it's true it will update the filter
 // run the eq operation and modify the filter variable
 if(dropMinutes && dropMinutes!=="all") {
 filter = filter.eq("minutesText", dropMinutes);
  }

 // check if there is a dropdown value and the value is not all
 // if it's true it will update the filter
 // run the eq operation and modify the filter variable
 if(dropData1 && dropData1 !=="all") {
 filter = filter.eq("data1", dropData1 );
  }
 // check if there is a input value and the value is not "Any"
 // if it's true it will update the filter
 // run the contains operation and modify the filter variable
 if(searchbar && searchbar !== "Any") {
 filter = filter.contains("aboutMe", dropMinutes);

  }

 // filter the dataset with the filter options builded
 // await for the dataset to be filter
 // before running the next line
 await $w('#dataset1').setFilter(filter);

 // after the dataset is filter getting the total records
 // and saving it in the 'ttl' variable
 let ttl = $w('#dataset1').getTotalCount();

 console.log(`dataset filtered total found : ${ttl}`)
}


@salman-hammed Unfortunately, no change !

Here my codes and I’ve attached a screenshot result below.

import wixData from ‘wix-data’ ;

$w.onReady( function () {

// Update UI
// build dropdown options from the databases
buildDropOptions( “LinePlan” , “minutesTexts” , “dropMinutes” );
buildDropOptions2( “LinePlan” , “data1” , “dropData1” );

// Handle events
// run ‘initFilter’ on dropdown changes
$w( ‘#dropMinutes, #dropData1’ ).onChange(initFilter);
// run ‘initFilter’ on button click

});

async function buildDropOptions(LinePlan, minutesTexts, dropMinutes) {
if (!LinePlan) throw new Error( “Collection Name is required!” );
if (!minutesTexts) throw new Error( “fieldkey is required!” );
if (!dropMinutes) throw new Error( “dropdown id is required!” );

// remove dublicate value in an object
const removeDublicate = items => [… new Set(items.map(item => item[minutesTexts]))];
// conver array into dropdoptions [“foo”] => [{label: “foo”, value:“foo”}]
const buildOptions = _ => _.map(curr =>({ label: curr, value: curr }));

// fetch the data from the database
const res = wixData.query(LinePlan)
.ascending(minutesTexts)
.limit( 1000 )
.find()

const title = removeDublicate(res.items);
let opts = buildOptions(title);
opts.unshift({ “label” : “All” , “value” : “All” })
$w( “#dropMinutes” ).options = opts;
}

async function buildDropOptions2(LinePlan, data1, dropData1) {
if (!LinePlan) throw new Error( “Collection Name is required!” );
if (!data1) throw new Error( “fieldkey is required!” );
if (!dropData1) throw new Error( “dropdown id is required!” );

// remove dublicate value in an object
const removeDublicate = items => [… new Set(items.map(item => item[data1]))];
// conver array into dropdoptions [“foo”] => [{label: “foo”, value:“foo”}]
const buildOptions = _ => _.map(curr =>({ label: curr, value: curr }));

// fetch the data from the database
const res = wixData.query(LinePlan)
.ascending(data1)
.limit( 1000 )
.find()

const title = removeDublicate(res.items);
let opts = buildOptions(title);
opts.unshift({ “label” : “All” , “value” : “All” })
$w( “#dropMinutes” ).options = opts;
}

// filter the dataset based on the input changes
async function initFilter() {
// save the filter in a variable
// we will update thie variable
// based on user inputs
let filter = wixData.filter();

// get all the values from selectors and store it in a const
const dropMinutes = $w( ‘#dropMinutes’ ).value;
const dropData1 = $w( ‘#dropData1’ ).value;

// check if there is a dropdown value and the value is not all
// if it’s true it will update the filter
// run the eq operation and modify the filter variable
if (dropMinutes && dropMinutes!== “all” ) {
filter = filter.eq( “minutesText” , dropMinutes);
}

// check if there is a dropdown value and the value is not all
// if it’s true it will update the filter
// run the eq operation and modify the filter variable
if (dropData1 && dropData1 !== “all” ) {
filter = filter.eq( “data1” , dropData1 );
}
// check if there is a input value and the value is not “Any”
// if it’s true it will update the filter
// run the contains operation and modify the filter variable

// filter the dataset with the filter options builded
// await for the dataset to be filter
// before running the next line
await $w( ‘#dataset1’ ).setFilter(filter);

// after the dataset is filter getting the total records
// and saving it in the ‘ttl’ variable
let ttl = $w( ‘#dataset1’ ).getTotalCount();

console.log(dataset filtered total found : ${ttl})
}

Thank you

Hello, Probably a silly question for you experts but I get an error saying wixUser not defined, what should this be?

this is my page code

I have called the wixUsers command at the top of the page
// For full API documentation, including code examples, visit Velo API Reference - Wix.com

import wixData from ‘wix-data’ ;
import wixLocation from ‘wix-location’ ;
import wixUsers from ‘wix-users’ ;

// …
export function button2_click(event) {
//…button to remove single item from dataset