"Liking" Posts in Repeater - Comprehensive

Hi Everyone,

I just added a “liking” feature to my repeater content. It’s virtually the same thing as liking an Instagram or FB post. Only logged in users can like posts, they can add or remove their likes, etc. It works exactly as you probably imagine.


I took somewhat of a unique approach. I created field called “likes” in one of my collections and then track the total likes by storing a JSON with all Member’s ID who has liked the post. I was concerned that parsing and stringifying JSON’s would cause lag time issues, but so far, it is working very well.

Some code experience will be necessary to implement it, but the pieces are effectively below:

// 
let likes_array = [];
 
$w.onReady(function () {
 setData();
});

setData() {
 
// .....Create and populate your repeater. Then within the onItemReady have the following code

// Check if any likes exist, parse the JSON and count how many users have liked each post. 
let likes = itemData.likes;                    
 if (likes) {
                        console.log(likes);
 let parsed_likes = JSON.parse(likes);
                        $w("#likes").text = parsed_likes.length.toLocaleString();
                    } else {
                        $w("#likes").text = (0).toLocaleString();
                    }

// For items that have likes, check to see if the current User was one of the likes, if so make heart full
if (itemData.likes) {
 if (itemData.likes.includes(wixUsers.currentUser.id)) {
            $w("#emptyHeart").hide();
            $w("#emptyHeart").collapse();
            $w("#fullHeart").show();
            $w("#fullHeart").expand();
            }
          }

// If a user is not logged in, prompt login before they can like anything
// Each time a heart is "toggled" run function to update collection. 
$w("#emptyHeart").onClick( (event) => {
 if (wixUsers.currentUser.loggedIn) {
 let $item = $w.at(event.context);
 // let data_item = itemData;
                        toggleHeart($item, itemData);
                        } else {
                            logIn();
                        }             
                    } );                                                                    
 
                    $w("#fullHeart").onClick( (event) => {
 let $item = $w.at(event.context);
 // let data_item = 
                        toggleHeart($item, itemData);                     
                    } );

// When empty heart is clicked, make it full and vise versa.
// Update the count by one depending on whether they like or unlike a post.
// Run the final functions which either add or remove a userId from the JSON.  
async function toggleHeart(item, itemData) {

 let emptyHeart = item("#emptyHeart");
 let fullHeart = item("#fullHeart");
 let likes = item("#likes");
 // toggle the fold at the index
 if (fullHeart.collapsed) {
        fullHeart.expand();
        fullHeart.show();
        emptyHeart.collapse();
        emptyHeart.hide();
 // await fullHeart.disable();
 await saveHeart(itemData);
 // fullHeart.enable();
        likes.text = (Number(likes.text) + 1).toLocaleString();
    }
 else {
        fullHeart.collapse();
        fullHeart.hide();
        emptyHeart.expand();
        emptyHeart.show();
 // await emptyHeart.disable();
 await deleteHeart(itemData);
 // fullHeart.enable();
        likes.text = (Number(likes.text) - 1).toLocaleString();
    }
 
}

async function saveHeart(itemData) {

if (!itemData.likes) {
        likes_array.push({
 "_id": wixUsers.currentUser.id
        })
        console.log(likes_array);
        itemData.likes = await JSON.stringify(likes_array);
        wixData.update("Project_Submission", itemData)
        .then( (results) => {
        });
    } else {
        likes_array = JSON.parse(itemData.likes);
        likes_array.push({
 "_id": wixUsers.currentUser.id
        })
        console.log(likes_array);
        itemData.likes = await JSON.stringify(likes_array);
        wixData.update("Project_Submission", itemData)
        .then( (results) => {
        });
    }

}

async function deleteHeart(itemData) {
    console.log("Delete Heart");
 if (itemData.likes) {
 let parsed_likes = JSON.parse(itemData.likes);
 let deleted_likes = parsed_likes.filter(function( obj ) {
 return obj._id !== wixUsers.currentUser.id;
 
});
    console.log(deleted_likes);
        itemData.likes = await JSON.stringify(deleted_likes); 
        wixData.update("Project_Submission", itemData)
        .then( (results) => {
 // console.log()
        });
    }

}
9 Likes

Very nice, David. I wondered why you would store all users and not just run a counter, but then I saw the fullHeart. Well done!

Very nice :wink:

Looks awesome!

Very nice. Thanks for sharing!

I am not sure what I am doing wrong, but this does not seem to be working for me. Is there any way you can provide a step by step walk through on this code?

This post is absolutely amazing, and perfect for my needs! It’s pretty much all up and running correctly with adapting it to my specs. Only issue I’m running into is with the saving aspect. I receive an error stating that the save has failed because "Items must be JavaScript objects.’

I’ve been doing and will continue to do research and reading on this, but so far nothing has connected the wires up there. It’s an old post but am commenting in case anyone still follows it and might know the solution.

Thank in advance! XD

I’m having trouble updating the old code. Does anyone know how to do that, or has someone already done it? I would greatly appreciate it.