How to display error caught from data.js to page code?

Hello, I was following a thread about preventing duplicate entries using a beforeInsert hook and it works. It does show an error message in the console.logs but it also shows the default submit failure message tied to the submit button. The default submit failure message I created was intended to let users know about the required fields. I would like to have another error message for the duplicate entry show up.

Here’s the code in my data.js

import wixData from 'wix-data';

export function searchForDuplicates(collection, field, item) {
    return wixData.query(collection)
        .eq(field, item[field])
        .find()
        .then((results) => {
            return results.items.length;
        })
        .catch((err) => {
            let errorMsg = err;
            
        });
}

export function test_beforeInsert(item, context) {
    return searchForDuplicates(context.collectionName, "emailAddress", item).then((res) => {
        if(res > 0) {   
            return Promise.reject('This item already exists');      
        }
        return item;
    });
}

Right now, it shows the “Please make sure to fill in all required fields.”
I would like to use the “Email already exists.” error for the duplicate entry.

Anyone?

You have to return the error, that way it is going to end up in the frontend.

let errorMsg = err
return errorMsg

@bwprado Thank you so much for responding. Would you be so kind enough to walk me through this? I assume I put it in the beforeInsert() function, how do I catch and show it in the frontend so I can do something like $w('#errorMsg).show()?

@chocookie22 I need to see your frontend code so I can see what you are doing with the backend. Could share it?

@bwprado Sure thing! Here it is:

import wixData from 'wix-data';
import wixUsers from 'wix-users';

let creator;

$w.onReady(function () {
    //GET CREATOR NAME
    wixData.query("Members/PrivateMembersData")
        .eq("_id", wixUsers.currentUser.id)
        .find()
        .then((results) => {
            creator = results.items[0].name;
            $w('#creatorField').value = creator
        })  
})

export function submitBtn_click(event) {
    $w('#dataset1').setFieldValue('createdBy', $w('#creatorField').value)
}

export function closeBtn_click(event) {
    $w('#dataset1').refresh();
}

It’s just a lightbox with some fields and a submit button. The code in data.js does prevent duplicate entry, I just need to show an error message in the frontend.

So, the way I see it, using hooks seem a little bit unnecessary to me, and also the problem you are facing. When the hook is called, you have know access to the return value cause it is being done at the backend with end point to return.

You could easily make this check just calling the searchForDuplicates() and dealing with the result.

The function would be like this in the backend:

import wixData from 'wix-data'

export async function searchForDuplicates(collection, field, item) {
    const query = await wixData.query(collection).eq(field, item[field]).find()
    return query.items //Return query
}

And the call in the frontend would be like this:

export async function submitBtn_click(event) {
    const checkDuplicates = await searchForDuplicates(
        'Clients', //Collection ID
        'clientName', //Field ID
        $w('#clientNameField').value //Value that will be used to check for duplicate entries
    )

    if (checkDuplicates.length > 0) { //If there IS a duplicate, then show error
        $w('#errorText').text = 'This item already exists'
        $w('#errorText').show()
    } else { //If not, then add the new client
        $w('#dataset1').setFieldValue('clientName', $w('#clientNameField').value)
        await $w('#dataset1').save()
        $w('#successText').show()
    }
}

Let me know if it works.

Hello Bruno! Terribly sorry it took me a while to reply. I sincerely appreciate your input and for taking the time to help me out.
I tried implementing the code you provided but it does not seem to work because it still saves the record. I just want to make sure I’m doing the right thing. All of this will be on my lightbox code, right?
Kindly check if the changes I’ve made are correct:

export async function submitBtn_click(event) {
    const checkDuplicates = await searchForDuplicates(
        'Clients', //Collection ID
        'clientName', //Field ID
        $w('#clientNameField').value //Value that will be used to check for duplicate
    )
    
    if (checkDuplicates) {
        $w('#dataset1').setFieldValue('clientName', $w('#clientNameField').value)
        await $w('#dataset1').save()
        $w('#successText').show()
    } else {
        $w('#errorText').show()
    }
}

@chocookie22 I’m so sorry, I made a terrible mistake that I did not take the proper care to look. It is a silly mistake in the if/else logical part. It is always returning true so it wouldn’t work properly. I’m going to post the solution in a second, hold on.

I just edited the code, I’m sorry for that.

@bwprado I’ve applied the changes that you made, the weird thing is it always shows the error message but the entry still goes through. Even for a unique entry, it still shows the error message.

@bwprado I tried it on both Preview mode and Published mode.
When I enter a unique client record, it gets added to the collection but this shows up in the console:


Same thing happens when I enter a client record who has the same name of an existing record:

I’m recreating your problem, and I need to know if you are saving the data using WIX Forms or did you create your own form? .setFieldValue() can only be used when you have a defined item, usually in a dynamic page. So .setFieldValue() would not work on a create new client form. I checked and the duplicate function is working properly, it shows the error and does not call the method above.

I highly appreciate all the help you’ve given and for being really patient with me. The submit button I have is connected to the dataset.


The input fields are connected to their corresponding fields as well. I guess this would be considered as WIX Forms? I’m terribly sorry, I’m new to this and I’m finding my way around. Could this be causing the problem? How will I correct this?


EDIT
About the line of code containing .setFieldValue(), kindly disregard that line as I have removed that. Sorry for the confusion.

@chocookie22 Can you show me the whole connection image please?

Here it is:

@chocookie22 I’m sorry, was this working before? Because I cannot see a way of working. You either use a form and save the client as a Contact or you create a form using the WIX Data API. The button submission is not submitting to anywhere, as I am aware of.

Your code should be something like this:

import wixData from 'wix-data'
import { searchForDuplicates } from 'backend/test'

export async function submitBtn_click(event) {
    const checkDuplicates = await searchForDuplicates(
        'Clients', //Collection ID
        'clientName', //Field ID
        $w('#clientNameField').value //Value that will be used to check for duplicate entries
    )
    console.log(checkDuplicates)

   if (checkDuplicates.length > 0) { //If there IS a duplicate, then show error
        $w('#errorText').text = 'This item already exists'
        $w('#errorText').show()
    } else { //If not, then add the new client
        const clientToInsert = { //Creates the client object to insert in the collection
            clientName: $w('#clientNameField').value,
            email: $w('#clientEmail').value,
            title: $w('#clientNameField').value,
        }

        const insertToCollection = await wixData.insert('Clients', clientToInsert)
        $w('#successText').show()
        $w('#successText').text = 'Client inserted!'

        console.log(insertToCollection)
    }
}

@bwprado Hello Bruno! The most recent code you provided works! I had to disconnect all the fields from the dataset as well as the submit button and it now works. I also changed something in the query part from this:

constquery=awaitwixData.query(collection).eq(field,item[field]).find()

To this:

constquery=awaitwixData.query(collection).eq(field,item).find()

Now the only concern is the form having lot of input fields. Does that mean I have to hardcode everything in? Is there a way for it to make it work while having the input fields/submit button connected to the dataset? Again, I am very thankful for all the help you’ve given.

@chocookie22 Yes, that part was off, I changed in the backend code but forgot to tell you. Nice that you caught it.

If you do not want to hard code everything, you should use WIX Forms to do it. It is way simpler and demands no coding, but you have less flexibility on the collections.

If you are willing to write the code, you just need to add the fields and values to the object clientToinsert that you create before inserting.

@bwprado For some reason, doing it with WIX Forms doesn’t work on the Published page but it does work on the Preview mode.

In the Published page, it always finds a duplicate and proceeds saving it. I guess the async/await doesn’t work properly with WIX Forms.