Save database via variable equivalent to field key?

I’ve been working on this for so long and learning all sorts of new javascript along the way and I’m getting so close to the functionality I want! Just need some help getting over the finish line.
I’m essentially trying to create an online course with dynamic pages (database name expData ) where users click a button to show they have completed a lesson. When they press the button, I get their userID, name, and what dynamic lesson page they’re on, and store it in a new database ( progressEXP ).

First I map the titles of my dynamic items to an abbreviation that corresponds with a field key in the progressEXP database. (i.e. a dynamic page called “Mosaic Mirror” is mapped to “mm_”)

const map1 = new Map();
    map1.set('Mosaic Mirror', "mm_"); 
    map1.set('Stepping Stone', "ss_");
    map1.set('Treasure Box', "tb_")

progressEXP database:

I then create the variable testField which is the current item title’s abbreviation + “L1”
(i.e. a dynamic page called “Mosaic Mirror” becomes “mm_L1”)

var currentItem = $w("#expData").getCurrentItem();
testField = [map1.get(currentItem.title)] + "L1";
console.log("Field key: " + testField); // expected output: "Field key: mm_L1"

So now my dynamic item pages are correlated with the field key value I want. When I console.log the testField variable I always get the correct value.

When someone presses the submit lesson button (“#statusBtn1”) on a dynamic page (ex. Item1):

  • Start by querying the “Members” data to get the current user info
  • Then query the “progressEXP” database to see if the user has already completed any lessons (if there is a value in the “completedLessons” field)
  • If there is already a row in the database for this user, then add a Boolean “true” to the correct database column (this works)
  • If there is not already a row in the database for this user, then insert them (works), and add a Boolean true to the correct database column (does not work)

The resulting database entry correctly inputs their name and ID, but does not set the testField value.

My full code is below.

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

const user = wixUsers.currentUser;
const userId = user.id;

$w.onReady(function () {
    var testField;
    const map1 = new Map();
    // map the dynamic item titles to an abbreviation that = a field key in the "progressEXP" database
    map1.set('Mosaic Mirror', "mm_"); 
    map1.set('Stepping Stone', "ss_");
    map1.set('Treasure Box', "tb_")

    $w("#expData").onReady(() => {
        var currentItem = $w("#expData").getCurrentItem();
        console.log(currentItem.title); // expected output: "Mosaic Mirror"
        console.log(map1.get(currentItem.title)); // expected output: "mm_"
        testField = [map1.get(currentItem.title)] + "L1";
        console.log("Field key: " + testField); // expected output: "Field key: mm_L1"

        $w("#statusBtn1").onClick(() => {
            $w('#statusBtn1').changeState("sectionComplete");
            //$w('#progressEXP').setFieldValue(`[testField]`, true);

            wixData.query("Members/PrivateMembersData")
                .eq("_id", userId).find()
                .then(m => { // get member info
                    let memberFirstName = m.items[0].firstName;
                    let memberLastName = m.items[0].lastName;
                    console.log(memberFirstName + " " + memberLastName)

                    wixData.query("progressEXP")
                        .eq("_id", userId).find()
                        .then(r => {
                            if (r.items.length > 0) {
                                console.log("existing");
                                // THIS WORKS IF there is a user in the DB
                                $w("#progressEXP").setFieldValue(testField, true);
                                $w("#progressEXP").save();
                                console.log(currentItem.title + " successfully completed");
                                
                            } else {
                                console.log("new");
                                let toSave = {
                                    "_id": userId,
                                    "firstName": memberFirstName,
                                    "lastName": memberLastName,
                                    testField: true, //this value does not get saved
                                };
                                console.log(toSave);

                                //store results in "progressEXP" database
                                wixData.save("progressEXP", toSave)
                                    .then((results) => {
                                        console.log(currentItem.title + " successfully completed");
                                    }).catch((err) => {});
                            }
                        })
                })
        })
    })
})

Basically I’ve created the variable testField and it is correctly saved to the database in this scenario:

$w("#progressEXP").setFieldValue(testField, true);
$w("#progressEXP").save();

But not in this scenario:

let toSave = {
    "_id": userId,
    "firstName": memberFirstName,
    "lastName": memberLastName,
    testField: true, //this value does not get saved
};

wixData.save("progressEXP", toSave)
.then((results) => {
    console.log(currentItem.title + " successfully completed");
})

Any thoughts?

The variable also works when performing a query on the database, once there is an item.

wixData.query("progressEXP")
            .eq("_id", wixUsers.currentUser.id)
            .eq(testField, true).find()
            .then((results) => {
                if (results.items.length > 0) {
                    $w('#statusBtn1').changeState("sectionComplete");
                    console.log(currentItem.title + " section 1 completed");
                } else {
                    $w('#statusBtn1').changeState("markComplete");
                    console.log(currentItem.title + " section 1 not completed");
                }
            })

So my only problem is that the following code does not save the testField variable to its corresponding field key in the database.

let toSave = {
    "_id": userId,
    "firstName": memberFirstName,
    "lastName": memberLastName,
    testField: true,  // this value does not get saved
};

//store results in "progressEXP" database
wixData.save("progressEXP", toSave)
    .then(() => {
    console.log(currentItem.title + " successfully completed");
})

I’ve also tried the following, saving each thing individually, but it does not work because I get an error saying there is no current item. Which I take to mean that the ID is not getting saved before the testField variable.

$w("#progressEXP").setFieldValue("_id", userId);
$w("#progressEXP").setFieldValue("lastName", memberLastName);
$w("#progressEXP").setFieldValue("firstName", memberFirstName);
$w("#progressEXP").setFieldValue(testField,true);
$w("#progressEXP").save();

Are there any other ways to approach this problem?

In your whole code i just see → " testField "

But at this code-part…you have —> testField1 ???

let toSave=	{
	"_id": userId,
	"firstName": memberFirstName,
	"lastName": memberLastName,
	testField1: true,// this value does not get saved
};

—> where is the declaration for testField1 ???

@russian-dima Yes that was my mistake in the post, I’ve been making small changes to clean up the code and I copied the wrong section. The post is correct now, but the issue still persists.

It’s a long shot, but you end the toSave object with a comma after “true”. Kill it, see what happens.

Damn! Really?
I saw it too, but never expected it could be the comma.
Giri did you test it already? Or do you just assume it?

@lmeyer Do not forget to tell me the result of GIRI’s suggestion. Very interessting → because i do not want to reconstruct all this, just to test it out xD.

I am very lazy xD. :grin:

@russian-dima @giri-zano Thanks for your response, but nope that didn’t change anything :confused:

1 Like

@lmeyer

Try this one…

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

const user = wixUsers.currentUser;
const userId = user.id;

$w.onReady(function () {
    var testField;
    const map1 = new Map();
    map1.set('Mosaic Mirror', "mm_"); 
    map1.set('Stepping Stone', "ss_");
    map1.set('Treasure Box', "tb_")

    $w("#expData").onReady(() => {
        var currentItem = $w("#expData").getCurrentItem();
        console.log(currentItem.title); // expected output: "Mosaic Mirror"
        console.log(map1.get(currentItem.title)); // expected output: "mm_"
        testField = [map1.get(currentItem.title)] + "L1";
        console.log("Field key: " + testField); // expected output: "Field key: mm_L1"

        $w("#statusBtn1").onClick(() => {
            $w('#statusBtn1').changeState("sectionComplete");
            //$w('#progressEXP').setFieldValue(`[testField]`, true);

            wixData.query("Members/PrivateMembersData")
            .eq("_id", userId).find()
            .then(m => { // get member info
                let memberFirstName = m.items[0].firstName;
                let memberLastName = m.items[0].lastName;
                console.log(memberFirstName + " " + memberLastName)

                wixData.query("progressEXP")
                .eq("_id", userId).find()
                .then((r)=> {console.log(r);
                    let items = r.items; console.log(items)  //<--- just one item ???

                    if (r.items.length > 0) {console.log("Data found!");
                        //... do something here.....
                        //... do something here.....
                        //... do something here.....
                    } 
                    else {console.log("No DATA found!");
                       items._id = userId;
                       items.firstName = memberFirstName;
                       items.lastName = memberLastName;
                       items.testField = true;
                       
                        wixData.save("progressEXP", items)
                       .then((results) => {
                           console.log(currentItem.title+" successfully completed");
                       }).catch((err) => {});
                    }
                });
            });
        });
    });
});

If not change this part…

items.[0]_id = userId;
items.[0]firstName = memberFirstName;
items.[0]lastName = memberLastName;
items.[0]testField = true;

If still not working …
show CONSOLE-LOG of —>

console.log(items)

Open the object & do a screenshot.

@russian-dima No luck, I get the following console error

And when I console items it returns empty

@lmeyer
Ok at first sorry for my stupid error… (and yes, if there is no item, there also is no object, right? → then you can not use this one…).

items[0]._id = userId;
items[0].firstName = memberFirstName;
items[0].lastName = memberLastName;
items[0].testField = true;

Second…
Of course the item must be EMPTY —> since —> No data found- section!
I did not pay attention!

else {console.log("No DATA found!");

So why you use SAVE and not → INSERT ?

let toInsert=   {
    "_id": userId,
    "firstName": memberFirstName,
    "lastName": memberLastName,
    testField: true
};

Or… last one xD…

var toInsert = new Object();

toInsert["_id"] = userId;
toInsert["firstName"] = memberFirstName;
toInsert["lastName"] = memberLastName;
toInsert[testField] = true;
wixData.save("progressEXP", toInsert).then((results)=>{//..............continue....

@giri-zano @russian-dima I FIGURED IT OUT :partying_face:
Sorry, I ignored your advice @russian-dima :joy:

Instead of this setup which didn’t work

let toSave = {
    "_id": userId,
    "firstName": memberFirstName,
    "lastName": memberLastName,
    testField: true,  // this value does not get saved
};

//store results in "progressEXP" database
wixData.save("progressEXP", toSave)
    .then(() => {
    console.log(currentItem.title + " successfully completed");
})

I did the following, which first saves the name and ID, then refreshes the database to guarantee the item is there, then successfully saves the testField variable

let toSave = {
    "_id": userId,
    "firstName": memberFirstName,
    "lastName": memberLastName,
};

//store results in "progressEXP" database
wixData.save("progressEXP", toSave)
    .then(() => {
        $w("#progressEXP").refresh()
        .then(() => {
            $w("#progressEXP").setFieldValue(testField, true);
            $w("#progressEXP").save();
        })
        console.log(currentItem.title + " successfully completed");
})

There might be a more elegant way(?) but this works!!

@lmeyer
Well done. So the issue was just a missing object.
You surely wanted to keep the save-command to be able to save with a specific ID? Thats why you did not want to use INSERT?

@russian-dima Yes exactly, I tried saving each individually but got an error saying there was no object. So I figured out I had to save the _id first, then update the database using refresh , then add the testField using save , to keep everything together per user.
I could probably use insert for the initial command, but save is essential for adding the testField value to the same item.

@lmeyer Just wanted to let you know about this…

import wixData from 'wix-data';

let toInsert = {
  "_id":          "00001",
  "title":        "Mr.",
  "first_name":   "John",
  "last_name":    "Doe"
};

wixData.insert("myCollection", toInsert)
	.then( (results) => {
		let item = results; //see item below
	} )
	.catch( (err) => {
		let errorMsg = err;
	} );

/*  item is:
 *
 *  {
 *    "_id":          "00001",
 *    "_owner":       "ffdkj9c2-df8g-f9ke-lk98-4kjhfr89keedb",
 *    "_createdDate": "2017-05-24T12:33:18.938Z",
 *    "_updatedDate": "2017-05-24T12:33:18.938Z",
 *    "title":        "Mr.",
 *    "first_name":   "John",
 *    "last_name":    "Doe"
 *  }
 */

For future coding :wink: