[SOLVED] Displaying Item Owner name on a dynamic Item page

Hello,

I have a site where Members can create Items that can then be viewed by all Users (whether or not they are Members) on dynamic Item pages.

I am trying to show the Member name next to the Item name on the dynamic Item page so that people can know who created the Item. I then want to add a link from the Member name to the Member’s profile page (that part is easy).

I have set up a Hook on my Item collection to generate the _owner field text after query on the corresponding Item #dynamicDataset. I place this _owner text into a hidden #AuthorID text box, which I then use as a reference to filter the Members #dataset5 on the page to only the Member whose ID matches the Item’s _owner field text. I have a separate visible text box on the page connected to the Member dataset’s Name text field to show the Name on the page after filtering. The problem is…

$w.onReady(function () {
 //TODO: write your page related code here...
    $w("#dynamicDataset").onReady(() => {
        populateCalculatedFields();
    });

    function populateCalculatedFields() {
        const currentAsset = $w("#dynamicDataset").getCurrentItem();
        const ownerID = currentAsset.authorID;
        $w("#AuthorID").text = ownerID;
    }
    $w('#dataset5').onReady(() => {
        $w('#dataset5').setFilter(wixData.filter()
            .eq('_id', $w("#AuthorID").text)
        );
    });

… the above code works in Preview (with me as logged in Member) but not in the Published site (with no-one logged in). All this code is placed within the page’s onReady function.

Is there a way to use the _owner field of my Item collection to then display the Member name who created the Item on the Item’s dynamic Item page for any User to see?

Any advice would be immensely appreciated here.

Thank you.

1 Like

Never just test your website using preview mode if you are using anything connected to Members data etc, as you will find that a lot of things in Wix only work fully when viewing on your published site.

Indeed, hence my query - works in Preview, not in Published.
Any thoughts on how to solve this?

@nicolasforzy In the code you pasted you missed “})” at the end of the code. I’m not saying that’s the reason (maybe you just didn’t copy it).
Anyway, check the database permissions, maybe they’re not set.

@jonatandor35 I didn’t paste the end “})”, you’re right, because I have other code below that doesn’t relate to this problem (and doesn’t affect its result).

As for database permissions, I’m only extracting data to read, so I don’t see how permissions can be a problem. Also, I can’t control permissions for the Members collection since it’s the Wix own collection with fixed parameters.

I’m basically at a loss…

Any ideas?

@nicolasforzy

J.D. is on the right path with dataset and collection permissions as the MembersPrivateData collection is site member author read only.
https://support.wix.com/en/article/corvid-wix-members-privatemembersdata-collection-fields
So, in other simple words, only the actual site member can see their own info from that collection.

That is what I have done on my members profile page with a simple text box connected to their name, so that it is displayed as a simple ‘Username’ when they look at that own profile page.

If you are wanting to have members names show up in public pages, then you need to have that info stored in another dataset that anybody can read the data from.

J.D. is correct when mentioning about dataset modes and collection permissions, they are two different settings, however they can affect each other.
https://support.wix.com/en/article/working-with-dataset-modes-and-collection-permissions
https://support.wix.com/en/article/about-collection-permissions
https://support.wix.com/en/article/changing-your-database-collection-permissions
https://support.wix.com/en/article/setting-up-a-dynamic-page-dataset

As Wix state:
When you preview your site, you do so in the Admin role. To interact as another type of user, first publish your site and then either log in as a different user ( Site member ) or not log in at all ( Anyone *). Remember that your live site works with the live collections and not with the sandbox collections you see in the Data Manager or when previewing your site. *

@givemeawhisky “If you are wanting to have members names show up in public pages, then you need to have that info stored in another dataset that anybody can read the data from.”

That’s definitely a solution, but I couldn’t figure out how to do it.

Basically, I would need to copy the Members fields that I want (ID, nickname and slug) into a separate collection that I could let anyone view. I assume I need to do that through code, some kind of automated query that uses the results to populate a new collection?

Or would that be a router hook that runs just after a member registers?

Any thoughts on this would be a big help, to me and to the community because I think this could be something that a lot of people could use.

Thanks in advance!

If you are wanting public users to see your members info, then why not create something like this using the members profile setup and instead of having it as a member profile, simply change the pages to be what your members want shown on their public profile.
https://support.wix.com/en/article/corvid-tutorial-building-your-own-members-area

This then gives the members overall control on what they do want and what they don’t want to be made public, like email and telephone numbers for example. They might have used their own in their members profile, however for the public they would prefer their general company email and telephone number instead.

Then the dataset that you used to store their selected choices in can then be used on a public page which displays in a repeater what each member wants to be made public.

That’s a good idea, though I’m using the standard Wix Members signup but I’ve added some inputs that Members can choose to enter at their discretion, so I can just make their visible name one of those inputs and encourage them to enter one.

However, that doesn’t resolve another issue I have: I want people to be able to click on the name in the dynamic page and be taken to the Member’s public Community page. For that, I either need:

  1. the Member’s slug field entry from the Members/PrivateMembersData collection, or;

  2. the Member’s Community Page URL
    I think 2. is the easiest, but I don’t know where I can find that or link it somehow to the Owner’s ID from my dynamic dataset.

Any ideas are, once again, greatly appreciated!

Just make up your own custom login and signup lightboxes and set them to open up instead of using Wix own windows, all of your custom fields that you enter on the signup form will be added to contacts and you can get to it via Wix Crm.
https://support.wix.com/en/article/corvid-enabling-custom-site-registration
https://www.youtube.com/watch?v=QbH8_eudjbE
https://www.youtube.com/watch?v=9eGhGfCiAbo
https://support.wix.com/en/article/adding-custom-fields-to-contacts

You can’t use the MembersPrivateData collection as that is read only to the site member author, so only that logged in member can see their own data.
https://support.wix.com/en/article/corvid-wix-members-privatemembersdata-collection-fields

This is where using that public profile form option from earlier and having that separate public profile dataset comes into play as you can simply match the id and email fields in that collection without having to worry about not being able to use the dataset.

You can use Wix CRM amd the email contact function.
https://www.wix.com/corvid/reference/wix-crm.html#emailContact
https://www.wix.com/corvid/reference/wix-crm-backend.html#emailContact
https://support.wix.com/en/article/corvid-tutorial-sending-a-triggered-email-to-contacts
https://support.wix.com/en/article/corvid-tutorial-sending-a-triggered-email-to-members

For more info about login api go here.
https://www.wix.com/corvid/reference/wix-users.html#login

For more info about the register api go here.
https://www.wix.com/corvid/reference/wix-users.html#register
Look at ‘Register a user as a site member with registration options’ code example and you will see where to put your additional custom fields in your code.

You do deserve your ‘Forum Ninja’ attribute, that’s for sure!

So, now I’m trying to be sneaky and playing with permissions in the backend. Here’s what I have so far:

FRONT END on page

$w.onReady(function () {
 //Generates authorID field from the _owner field with an afterQuery() hook on the underlying collection
    $w("#dynamicDataset").onReady(() => {
        populateCalculatedFields();
    });

    function populateCalculatedFields() {
 // Get the Owner ID of the dynamic page's displayed Item and displays it in a text box on the page (as a check)
       const currentAsset = $w("#dynamicDataset").getCurrentItem();
       const ownerID = currentAsset.authorID;
       $w("#AuthorID").text = ownerID;

 // Runs backend function of wixdata.get() on Members/Private collection, with bypassed permissions check through options, using Owner ID as Member _id
       return getSlug(ownerID)
            .then((result) => {
 // Aims to extract fields from results to populate text boxes on the page with relevant data from Members/Private collection
                let item = result.item;
                let nickname = result.nickname;
                let slug = result.slug;
                $w('#Author').text = nickname;
                $w('#AuthorSlug').text = slug;
 // FAILS...
              });
    }
 });

BACKEND in a separate module

import wixData from 'wix-data';

let options = {
 "suppressAuth": true
}

export function getSlug(ownerID) {
    wixData.get('Members$PrivateMembersData', ownerID, options)
        .then((result) => {
              let item = result;
              let nickname = result.nickname;
              let slug = result.slug;
              console.log(result.item);
        })    
}

The missing link is how to extract the result of the backend data query back into the main page, given that I first have to extract the dynamic item’s _owner data first to have an _id to match in the Members Private collection.

Any thoughts or ideas are, as always, greatly appreciated :slight_smile:

@givemeawhisky
HAHAHAHAHAHAHAHA! (evil maniacal laugh) I SOLVED IT!!!

So, here’s what I did, which I checked in the published version of the site and it WORKS!!!

HOOK - saved in backend/data.js

export function Characters_afterQuery(item, context) {

 // This creates a field named 'authorID' containing the _owner ID of any item returned whenever a query is performed on the 'Characters' collection
    item.authorID = item._owner;
    return item;
}

BACKEND CODE - saved as module secureSlug.jsw

import wixData from 'wix-data';

// This makes sure the function gets the variable from the frontend as 'ownerID'
export function getSlug(ownerID) {

  // This bypasses the permissions check so the query can run for any user, not just the Member who owns the asset
 let options = {
 "suppressAuth": true
    }
 
 // This runs the query with the above option in place and finds the Member who's ID matches the _owner ID of the Item displayed on the dynamic page
 return wixData.query('Members/PrivateMembersData')
        .eq('_id', ownerID)
        .find(options)
}

FRONTEND CODE

$w.onReady(function () {
    $w("#dynamicDataset").onReady(() => {
    
    // This launches the hook outlined above when the dataset is ready, because the dynamicDataset is linked to the 'Characters' collection
        populateCalculatedFields();
    });

 function populateCalculatedFields() {
         // This creates the authorID field containing the dynamic item's _owner ID
         const currentAsset = $w("#dynamicDataset").getCurrentItem();
         const ownerID = currentAsset.authorID;
 
         // This placed the _owner ID of the dynamic item in a hidden text box as a check
         $w("#AuthorID").text = ownerID;
        
         // This passes the ownerID variable to the backend function above
         getSlug(ownerID)
                 // Note that the .find instruction is in the backend (where permissions are bypassed through code above) but the .then instruction is here in the frontend, so that I can access the elements of the returned item and define fields to use on the page
                .then((results) => {
                     let item = results.items[0];
                     let nickname = item.nickname;
                     let slug = item.slug;
                     // This is a check to make sure the right item is returned
                     console.log(results);
                     
                     // This inserts the dynamic item owner's nickname (from the Members/PrivateMembersData collection) into a text box on the dynamic page to show them as the author of the dynamic item displayed
                     $w('#Author').text = nickname;
                     
                     // This inserts the dynamic item owner's slug (also from the Members/PrivateMembersData collection) into a text box on the dynamic page so I can use it to create a link to their profile page that people can access by clicking on the owner's name (through an onClick(event) code using wixLocation.to)
                     $w('#AuthorSlug').text = slug;
                })
    }
})

Voila :slight_smile:

Comments or thoughts on this are very welcome, and a big thank you to everyone who helped me in the above comments because your ideas pushed me into the right direction and, eventually, the solution!

1 Like

Good work Nicolas, I was so thinking about just doing the public profile way that I totally forgot about using the data options method through the backend to bypass it all.
https://www.wix.com/corvid/reference/wix-data.html#WixDataOptions

It has all come back to me today what with seeing your code with the supressAuth in it and also reading through Wix CRM backend too while I was looking at something else too.

When should I write code in the backend instead of the client side?
You may want to write your code in the backend in the following cases:

  • When you don’t want visitors to view or manipulate code containing sensitive information such as payment details or API keys.

  • When you perform security checks or validations that expose private data such as emails and passwords.

  • When you’ve set your collection permissions so that a particular role cannot access a collection, but you want visitors with that role to partially access the collection in some manner. In this case you can suppress permission checks using suppressAuth.
    So great that you’ve got it all working for yourself, always a better feeling when you’ve worked it out for yourself and not have to had somebody else point out your mistake or the way to do it correctly to you.
    :+1::+1:

Hello Nicolas
I have been looking for this solution for many months, but I have a problem, it tells me that the getSlug value is not defined, I am relatively new in this and I understand many things, but I could not find the solution. Can you help me?

This is in the back end

I really did not want to ask for help, but it surpasses me a lot

Check that your code in your secureSlug.jsw is the same as what is shown in Nicolas’ example.

Plus, afterQuery is a datahook that must be placed through your data.js in the backend, again see Nicolas’ example as it clearly states that too.

See here for more info about them.
https://www.wix.com/corvid/reference/wix-data.Hooks.html

To add a hook to a collection, in the Content Manager click on the Hooks button and choose which hooks to add. Code for the hooks is written in the data.js file which resides in Backend section of your site. Hook functions are defined using the following pattern:

export function <collectionName>_<hookName>(<parameters>) { }

Thanks! will check the info!!

hi
thank you for sharing your code!! its realy good! i need to create somthing similar.
i have reapter that display feedbacks with the name of the guide that fill every feedback. i display the data on repeater and in addition i want to present the name of the guides (owner).
can you help me?