[SOLVED] Filter repeater based on Member Role

EDIT: Solved, with solution and code sample in a comment below.
I’m trying to use a repeater to display what a user has access to based on their role. I use the code below to get the current user’s member role, then use a filter to show the items they have access to.

The code works if a user only has access to one item, but the problem is that it if a user has access to 2 or more items, the filter only returns one instead of multiple.

How can I change this filter setup to display multiple items to users with multiple roles? Or is there a simpler / more elegant way to accomplish this? I’m assuming my logic/setup is faulty. I’m by no means a pro, but I’ve been searching the forum for days and I feel like I’ve gotten so close! I’ll take any advice/references I can get.


My setup:
• Three strips, all collapsed on load. One strip (“stripLoading”) says “loading” and loads immediately, one strip (“repeaterStrip”) contains the repeater and expands when the filter is finished, one strip (“stripNoOrders”) says “No Orders” and expands if the user has no role.
• A repeater with elements linked to a dataset
• A database named “ocDataset”
• A field in the database named “roleFilter” with tags for each item
• Code to filter the data based on the “roleFilter” tags

My code: (shortened; I have 7 roles total)

import wixUsers from 'wix-users';
import wixWindow from 'wix-window';
import wixLocation from 'wix-location';
import wixData from 'wix-data';

let user = wixUsers.currentUser;

$w.onReady(function () {
    $w('#stripLoading').expand();
 if (user.loggedIn) {
        user.getRoles()
            .then((roles) => {

 if (roles.some(r => r.name === "EXP Mosaic Mirror")) {
                    $w("#ocDataset").setFilter(wixData.filter()
                            .eq("roleFilter", "expMM")
                        )
                        .then(() => {
                            console.log("Dataset is now filtered");
                        })
                        .catch((err) => {
                            console.log(err);
                        });
                    $w('#stripLoading').collapse();
                    $w('#repeaterStrip').expand();
                } else {
                    $w('#stripLoading').collapse();
                    $w('#stripNoOrders').expand();
                }

 if (roles.some(r => r.name === "EXP Treasure Box")) {
                    $w("#ocDataset").setFilter(wixData.filter()
                            .eq("roleFilter", "expTB")
                        )
                        .then(() => {
                            console.log("Dataset is now filtered");
                        })
                        .catch((err) => {
                            console.log(err);
                        });
                    $w('#stripLoading').collapse();
                    $w('#repeaterStrip').expand();
                } else {
                    $w('#stripLoading').collapse();
                    $w('#stripNoOrders').expand();
                }
            });
    }
})

You should do something like:

let isMosaicMirror = false, isTreasureBox = false;
if (roles.some(r => r.name === "EXP Mosaic Mirror")) {
isMosaicMirror = true;
}
if (roles.some(r => r.name === "EXP Treasure Box")){
isTreasureBox = true;
}
let filter = wixData.filter();
    if(isMosaicMirror && isTreasureBox){
        filter = filter.eq("roleFilter", "expMM").or(filter.eq("roleFilter", "expTB"));
    } else if(isMosaicMirror ){
        filter = filter.eq("roleFilter", "expMM");
    } else if(isTreasureBox ){
        filter = filter.eq("roleFilter", "expTB");
    }
$w("#dataset").setFilter(filter).then(r => {
//etc...
})

Thanks so much for your reply and suggestion! I tweaked the code and it works great to show the variations possible for these 2 roles.

Followup question: I have 7+ roles. With this setup, would I have to manually account for each possible combination of roles? Or am I misinterpreting the code?

i.e. Would I have to create code for:
Role1 && Role2
Role1 && Role2 && Role3
Role1 && Role3
Role1 && Role3 && Role4
etc…

(If my math is correct there are over 5000 possible combinations of 7 different roles :sweat_smile:)

@lmeyer In that case you should loop thorough the roles:

let roleValues = [
{role: "EXP Treasure Box", value: "expTB"},
{role: "EXP Treasure Box" , value: "expMM"},
//etc... all 7 roles
]
let filter = wixData.filter();
let roles = r.map(e => e.name);
let relevantValues = roles.map(e => roleValues.find(i => i.role === e).value);
filter = filter.eq("roleFilter", relevantValues[0]);
relevantValues.shift();
if(relevantValues.length > 0){
relevantValues.forEach(e => {
filter = filter.or(wixData.filter().eq("roleFilter", e));
})
}
$w("#dataset").setFilter(filter).then(r => {
//etc...
})

@jonatandor35 Awesome! Thanks so much for helping me work through this! We’re getting so close. I’m just getting an error that “r” is undefined. My page code is below if you could help me out:

import wixUsers from 'wix-users';
import wixWindow from 'wix-window';
import wixLocation from 'wix-location';
import wixData from 'wix-data';

let user = wixUsers.currentUser;
$w.onReady(function () {
    $w('#stripLoading').expand();
    $w('#repeaterStrip').collapse();
 if (user.loggedIn) {
        user.getRoles() 
            .then(()  => {
 let roleValues = [
                {role: "EXP Treasure Box", value: "expTB" },
                {role: "EXP Treasure Box", value: "expMM" },
                {role: "ncGrade1", value: "nc1" },
                {role: "ncGrade2", value: "nc2" },
                 ]   //etc
 let filter = wixData.filter();
 let roles = r.name; // 'r' is not defined
 let relevantValues = roles.map(e => roleValues.find(i => i.role === e).value);
                filter = filter.eq("roleFilter", relevantValues[0]);
                relevantValues.shift();
 if (relevantValues.length > 0) {
                    relevantValues.forEach(e => {
                        filter = filter.or(wixData.filter().eq("roleFilter", e));
                    })
                }
                $w("#ocDataset").setFilter(filter).then(() => {
                        console.log("filtered");
                        ordersView();
                    })
                    .catch((err) => {
                        console.log(err);
                    });
            })
    }
})

I know previously I had defined it like so:

if (roles.some(r => r.name === "Admin"))

Where in this new code should it be defined? Again thank you for all your help.

@lmeyer instead of this line:

user.getRoles() 
.then(()  => {

Write:

user.getRoles() 
.then(r => {

@jonatandor35 I really appreciate your guidance with this! I made the fix and get no more errors in the Editor, but on the live site the code is not working…
I ran some console logs to check where it gets stuck and I get some errors around the “let relevantValues = roles.map” line. Any ideas for a fix?

My code below:

import wixUsers from 'wix-users';
import wixWindow from 'wix-window';
import wixLocation from 'wix-location';
import wixData from 'wix-data';

let user = wixUsers.currentUser;

$w.onReady(function () {
    $w('#stripLoading').expand();
    $w('#repeaterStrip').collapse();
 if (user.loggedIn) {
        user.getRoles()
            .then(r => {
 let roleValues = [
                 {role: "EXP Treasure Box", value: "expTB" },
                 {role: "EXP Treasure Box", value: "expMM" },
                 {role: "mcGrade1", value: "nc1" },
                ] //etc
                console.log("roles defined");
 let filter = wixData.filter();
                console.log("let filter");
 let roles = r.name;
                console.log("let roles");
 let relevantValues = roles.map(e => roleValues.find(i => i.role === e).value);
                console.log("let relevant values"); // this message doesn't appear, so this is where it gets stuck
                filter = filter.eq("roleFilter", relevantValues[0]);
                console.log("filter");
                relevantValues.shift();
                console.log("relevant values shift");
 if (relevantValues.length > 0) {
                    relevantValues.forEach(e => {
                        filter = filter.or(wixData.filter().eq("roleFilter", e));
                    })
                }
                $w("#ocDataset").setFilter(filter).then(() => {
                        console.log("Dataset is now filtered");
                        ordersView();
                    })
                    .catch((err) => {
                        console.log(err);
                    });
            })
    }
})

@lmeyer I guess you tried it with a user who has no roles.
Add a condition in the “then” part:

.then(r => { 
if(r.length > 0){
//the code here
}
})

@jonatandor35 I made the change and still no luck! I’m testing with a user that has several roles, but the repeater shows all roles instead of being filtered, and the code doesn’t move beyond the “let relevantValues = roles.map” line.
When I test on a user with no roles, the “if (r.length > 0) … else” works as expected to show the elements I want it to.

import wixUsers from 'wix-users';
import wixWindow from 'wix-window';
import wixLocation from 'wix-location';
import wixData from 'wix-data';

let user = wixUsers.currentUser;

$w.onReady(function () {
    $w('#stripLoading').expand();
 if (user.loggedIn) {
        user.getRoles()
            .then(r => {
 if (r.length > 0) {
 let roleValues = [
                 { role: "EXP Treasure Box", value: "expTB" },
                 { role: "EXP Treasure Box", value: "expMM" },
                 { role: "ncGrade1", value: "nc1" },
                    ]  //etc
                    console.log("roles defined");

 let filter = wixData.filter();
                    console.log("let filter");
 let roles = r.name;
                    console.log("let roles");
 let relevantValues = roles.map(e => roleValues.find(i => i.role === e).value); // still gets stuck around here, because the below console messages never appear
                    console.log("please work this time"); 
                    filter = filter.eq("roleFilter", relevantValues[0]);
                    console.log("filter log 1"); 
                    relevantValues.shift();
 if (relevantValues.length > 0) {
                        relevantValues.forEach(e => {
                            filter = filter.or(wixData.filter().eq("roleFilter", e));
                        })
                    console.log("filter log 2"); 
                    }
                    $w("#ocDataset").setFilter(filter).then(() => {
                        console.log("filtered");
                        ordersView();
                    })
                } else {
                    noOrdersView();
                }
            })
    }
})

@lmeyer I see. Sorry, I had a mistake.
Instead of:

 let roles = r.name; 

write:

let roles = r.map(e => e.name); 

@jonatandor35 No worries, you’re helping me learn a lot! I’m a bit outside my scope of knowledge with loops and maps, so I’m enjoying the crash-course. I made the change but unfortunately I encounter the same problem, except now with a different error in the console:

Relevant code:

let filter = wixData.filter();
                    console.log("let filter");
 let roles = roles.map(e => e.name);
                    console.log("let roles");
 let relevantValues = roles.map(e => roleValues.find(i => i.role === e).value);
                    console.log("let relevant values");
                    filter = filter.eq("roleFilter", relevantValues[0]);
                    relevantValues.shift();
 if (relevantValues.length > 0) {
                        relevantValues.forEach(e => {
                            filter = filter.or(wixData.filter().eq("roleFilter", e));
                        })
                    }
               $w("#ocDataset").setFilter(filter).then(() => {
                     console.log("Dataset is now filtered");
                        ordersView();
                    })

I guess this user has a role (or more) that is not included in the roleValues array.
so to solve that add after

let roles = r.map(e => e.name); 

The following line:

roles = roles.filter(e => roleValues.some(i => i.role === e));

@jonatandor35 Hey thanks so much again for your patience and assistance.
I made the changes and it’s still not filtering the repeater :thinking:

I get a slightly different error in the console, and now the code seems to stop where we added the new line:

Things I’ve done:
Changing the roleFilter field in the database to Text instead of Tags
Checking the permissions on the dataset
Double-checking that all IDs, role names, and field values are exact
Testing on a user with several combinations of multiple roles, multiple times
Including all roles in the roleValues array

The latest code:

$w.onReady(function () {
    $w('#stripLoading').expand();
    $w('#repeaterStrip').collapse();
 if (user.loggedIn) {
        user.getRoles()
            .then(r => {
 if (r.length > 0) {
 let roleValues = [
                {role: "EXP Treasure Box", value: "expTB" },
                {role: "EXP Treasure Box", value: "expMM" },
                {role: "ncGrade1", value: "nc" },
                {role: "PrinciplesExcellence", value: "poe" },
                    ] //etc 
                    console.log("roles defined");

 let filter = wixData.filter();
                    console.log("let filter");
 let roles = roles.map(e => e.name);
                    roles = roles.filter(e => roleValues.some(i => i.role === e));
                    console.log("let roles");
 let relevantValues = roles.map(e => roleValues.find(i => i.role === e).value);
                    console.log("let relevant values");
                    filter = filter.eq("roleFilter", relevantValues[0]);
                    relevantValues.shift();
 if (relevantValues.length > 0) {
                        relevantValues.forEach(e => {
                            filter = filter.or(wixData.filter().eq("roleFilter", e));
                        })
                    }
              $w("#ocDataset").setFilter(filter).then(() => {
                     console.log("Dataset is now filtered");
                        ordersView();
                    })
                } else {
                    noOrdersView();
                }
            })
    }
})

@lmeyer There’s a mistake here:

 let roles = roles.map(e => e.name); 

It should be:

 let roles = r.map(e => e.name);

By the way, instead of console.log(“some string”), you should log the relevant variable, so you’ll be able to locate the error. For example: console.log(roles)

@jonatandor35 YES it works!! :raised_hands:t2: Thank you so much for your help!

You’re welcome :slight_smile:

For anyone trying to accomplish the same thing, here’s my setup.

Shoutout to @jonatandor35 , a true Corvid Master, for the amazing help figuring out the code. Obviously tweak it to fit your setup.

• Three strips, all collapsed on load. One strip (“stripLoading”) says “loading” and loads immediately, one strip (“repeaterStrip”) contains the repeater and expands when the filter is finished, one strip (“stripNoOrders”) says “No Orders” and expands if the user has no role.

• Database with your fields, then add a field to filter by. Mine is “roleFilter” and I have tag values that correspond to each of my Roles. (With “admin” in all, so Admin get access to everything)

• Page code:

import wixUsers from 'wix-users';
import wixWindow from 'wix-window';
import wixLocation from 'wix-location';
import wixData from 'wix-data';

let user = wixUsers.currentUser;

$w.onReady(function () {
    $w('#stripLoading').expand();
    $w('#repeaterStrip').collapse(); 
 //collapse repeater until filter is complete
 if (user.loggedIn) {
        user.getRoles()
            .then(r => {
 if (r.length > 0) {
 let roleValues = [ 
 // role = role name, value = value in database field
          {role: "Role Name 1", value: "expTB" },
 // Change according to your Role names, and database field values
          { role: "Role Name 2", value: "expMM" },
          { role: "Role Name 3", value: "expSS" },
          { role: "Admin", value: "admin" },
          ] //etc, for as many roles as you have
                    console.log("roles defined");

 let filter = wixData.filter();
 let roles = r.map(e => e.name);
                    roles = roles.filter(e => roleValues.some(i => i.role === e));
                    console.log("roles", roles);
 let relevantValues = roles.map(e => roleValues.find(i => i.role === e).value);
                    console.log("relevant values", relevantValues);
                    filter = filter.eq("roleFilter", relevantValues[0]); 
 //"roleFilter" is the database field I'm filtering by.
                    relevantValues.shift();
 if (relevantValues.length > 0) {
                        relevantValues.forEach(e => {
                            filter = filter.or(wixData.filter().eq("roleFilter", e));
                        })
                    }
                    $w("#ocDataset").setFilter(filter).then(() => {
                console.log("Dataset is filtered");
                ordersView(); //function to show repeater
                    })
                } else {
                    noOrdersView(); 
                    //function if user has no roles
                }
            })
    }
})

function ordersView() {//function if user has roles
    $w('#repeaterStrip').expand();
    $w('#stripLoading').collapse();
}
function noOrdersView() {//function if user has NO roles
    $w('#stripLoading').collapse();
    $w('#stripNoOrders').expand();
}

BTW, in the roleValues array above, you put the same role twice, and this code will ignore the second one.

Well done you 2!

I am new to wix corvid and created a Dynamic page with items to be filtered between a certain months shown below.

I would like to add a badges filter so only members with specific badges can see certain items set in the database. Example members with bronx badge can only see bronx (tag or filtered) pages on certain months I followed the same steps and created a tag values and enter roles to be filtered but can’t use the code being discuss.

User A - Badge is set to “Bronx”
User B - Badge is set to “Brooklyn”
User C - Badge is set to “Manhattan”
User D - Badge is set to “Queens”
User E - Badge is set to “StatenIs”
User F - Badge is set to “Bronx” & “Brooklyn” & “Queens”

The dynamic page set with a Filter repeater based on Member Role with in the database.

  1. Bronx Badge - can only see filter Bronx (items/pages)
  2. Brooklyn Badge - can only see filter Brooklyn (items/pages)
  3. Manhattan Badge - can only see filter Manhattan (items/pages)
  4. Queens Badge - can only see filter Queens (items/pages)
  5. StatenIsBadge - can only see filter StatenIs (items/pages)

User F - Can see 3 filters “Bronx” & “Brooklyn” & “Queens” (items/pages)

Thank you :grin: