REST API data subset copied to appVar

I have looked at every MAP, SET_KEY, LOOKUP etc on the forum and my mind is not getting something that has to be simple.

REST API data loaded from dataVar to appVar - no problem, I let the AppVar get schema from dataVar with set appVar node.

The problem is when I need to copy a subset of fields from one appVar to another.

appVar.restApiData to appVar.fewerProperties

appVar.restApiData Schema (simplified)
id : 99999
name: john
[…] several more

appVar.fewerProperties (manually created and properties added)
id: -1
name: null
stat1 : -1
stat2: -1

What I need to do is copy to to

It’s so simple, but I can’t find the right combo of formulas.

I manage to get one entry into appVar.fewerProperties but never the entire list from the appVar.restApiData. It is a short list currently at 18 entries.

I have the IF (fake for loop) working just fine. Setting a loop counter.
I cycle through all 18 entries, popping up a toast to see that it is working.

I end up with 1 entry, [0] getting a value but not the other 17 undefined.

So could someone tell me the step inside the If/For loop that copies all 18 entries? @Mari since you seem to answer this question so often.

Before you ask here are some attempts. You can see I am lost. an long winded vars. if you do an example for me just use the simple vars above instead of these below.

Thank you

MAP<m>(appVars.campaignsAppVar, IF(index == appVars.loopPosition001AppVar, SET_KEY(m,“campaignId”, LOOKUP(appVars.CRVTactiveCampaignsAppVar[appVars.loopPosition001AppVar], “campaignId”)),m))

MAP(appVars.campaignsAppVar,IF(index == appVars.loopPosition001AppVar,SET_KEY(item, “campaignId”, appVars.CRVTactiveCampaignsAppVar[appVars.loopPosition001AppVar].campaignId), item))

MAP<campaigns>(appVars.campaignsAppVar,SET_KEY(campaigns, “campaignId”, appVars.CRVTactiveCampaignsAppVar[appVars.loopPosition001AppVar].campaignId))

Both appVars are List of Objects

1 Like

Finally stumbled on something that works. I had to SET_ITEM_AT the new storage appVar before the loop would work.

Am I doing this right? Why is the MAP statement alone not enough to copy values into another List of Objects ?? Is there a simpler way to do this? In the SET_ITEM_AT I have hard coded the appVar object properties. If the properties change this statement will not know about it and I assume fail or over write the appVar object. Any hints?

Begin LOOP

IF (appVars.loopPosition001AppVar < appVars.loopCount001AppVar)

SET_ITEM_AT(appVars.campaignsAppVar, appVars.loopPosition001AppVar, { campaignId: -1, campaignName: “”})

Now copy fields from another appVar init by dataVar record collection

MAP<m,i>(appVars.campaignsAppVar, IF(i == appVars.loopPosition001AppVar, SET_KEY(m,“campaignId”, LOOKUP(appVars.CRVTactiveCampaignsAppVar[appVars.loopPosition001AppVar], “campaignId”)),m))


Wait… First question. The second variable is a list of objects that have no value before this flow, right?

You may need to try this:

set app variable flow for the fewer properties and set the value there:

MAP<m>(appVars.campaignsAppVar, {id:, name:, stat1: m.stat1})

And you can add your manual properties there…

Also if you have the schema set up already you can simply use the “Mapping” binding and there just drag and drop corresponding properties…

The appVar above, beginning with CRVT, was set after dataVar was collected from an REST API. I am doing this in the global canvas and if I don’t output set dataVar into set appVAR I don’t see any data in other pages. Don’t know why?? Anyhow

That CRVT appVar has the schema of the original dataVar auto set by the set appVar flow and has data.

The appVars.campaignsAppVar is the manually created appVar setting with 13 properties. In this loop, I am coping two properties from CRVT to this object.

You cannot pass data variables between pages. That is why you can’t get the data out of the global canvas only in Appvars.

Okay, then maybe you are using the wrong variable in the map function.

Try using

MAP<m>(data.CRVT, {same as above.})

Thank you. It took me a while to discover that. I thought the dataVar being created on a GLOBAL canvas meant it was global.

I need to get data into appVars.camaignsAppVar.

Is your suggestion an outer wrapper MAP(data.CRVT, MAP "as I defiend above))

Why do you want to go through two lists?

What you want to do according to my understanding is that you have a list of objects and you want to create another list of objects based on that.

So you only need to go through the original list and set the next list to the formula above.
MAP()f function returns a list. That is important to understand. The retjmurn value is exactly what you need. A list of objects with the specified properties.

@Mihaly_Toth Thanks for the replies. I had the idea that the MAP function was going to change the data of the List parameter. Your last note made the light bulb come on. Thank you.

The NEW list has some static property values after the first load, and the others are counters that values need to accumulate, not reset. I am reading the API every 15 min for changes.

I realized how I might do it with nested MAPs and keep the counters in the first list and not overwrite them on every API read.

So how about this one? I shortened the properties down to make the point more clearly. It seems to be working.

This is in a setAppVar flow node setting campaignsAppVar

IF(i == appVars.loopPosition001AppVar,
IF(y == appVars.loopPosition001AppVar, {campaignId: m.campaignId, name:, stat15min: c.stat15min, stat30min: c.stat30min}, c)), m))

Why do you need this loopPosition? What is the purpose of that? Why do you feed 4 parameters into 2 MAP() functions? What is m,i, c,y?

MAP() function is a loop. It goest through each and every item in the first list. If the new list has static values then just overwrite it with the + function.
Okay, let me write what I understand:

You have an appVars.restList is a list of objects that looks like this

{campaignId, name, stat15min, stat30min, ...}, 
{campaignId, name, stat15min, stat30min, ...}, 

You have a different app variable let’s call it:
appVars.subListofRestList that looks like this:

{campaignId, name, stat15min, stat30min}, 
{campaignId, name, stat15min, stat30min}, 

So you have the same properties as in the other list. And also the stat15min and stat30min has some static value already that you want to add to another number. In this case the

“Set app variable” flow for the appVars.subListofRestList would have this value in the formula binding screen:

{campaignId: restList.campaignId, 
stat15min: FIND_BY_KEY(appVars.subListofRestList, "campaignId",, 
stat30min: FIND_BY_KEY(appVars.subListofRestList, "campaignId",})

Now this of course implies that appVars.subListofRestList already has the campaignId in it. You might want to add an IF into that to avoid issues on initial load like this:

{campaignId: restList.campaignId, 
stat15min: IF(IS_EMPTY(FIND_BY_KEY(appVars.subListofRestList, "campaignId",, 0, FIND_BY_KEY(appVars.subListofRestList, "campaignId",, 
stat30min: IF(IS_EMPTY(FIND_BY_KEY(appVars.subListofRestList, "campaignId",, 0, FIND_BY_KEY(appVars.subListofRestList, "campaignId",})

This would result in the following list of objects:

campaignId: from the restList, 
name: from the restList, 
stat15min: default value + value from the restList, 
stat30min: default value + value from restList

Note that I assumed that property of stat15min and stat30min is a number. If it is NaN (Not a Number) you might need to do a few further tricks to get it working correctly.

Using the MAP() function can be frustrating at times, but it is important to understand that MAP() doesn’t need any other input than a list. No index, nothing else. But the formula inside the MAP() with which you set the value to the items in the new array can contain data or variable from other variables. So you can keep your variables nice and clean. Optimising your variable screen by avoiding having tons of “index” variables.

I honestly hope that I got your issue correctly and this will help you solve your problems

Thank you for the additional info and the time taken to show how to do this task.

I did not provide clear enough guidance. The lists are not the same. They contain 2 properties that are the same, but ALL the other properties are different. stat15min etc are not in the list I am copying values from.

What a learning curve for me. It took me awhile to get what you showed me but I believe I got it now.

It took me many many times around creating several other successful versions but they all required index use. And a separate step to init null and -1 values to the new list.

Things like FIND_BY_KEY().stat15min is not something I would have thought about.

I reworked the formula based upon following your logic above. thank you again for taking the time to show me a better way to do things.

Here is a short version of what I have now. Which looks like your example but I had to jump thru my own hoops to finally get to the logic of what you did.

using a <set appvar flow function>

appVars.campaignsAppVar = 
campaignId: m.campaignId, 
stat15min: IF(IS_EMPTY(FIND_BY_KEY(appVars.campaignsAppVar, "campaignId", m.campaignId).stat15min), -1, FIND_BY_KEY(appVars.campaignsAppVar, "campaignId", m.campaignId).stat15min), 
stat30min: IF(IS_EMPTY(FIND_BY_KEY(appVars.campaignsAppVar, "campaignId", m.campaignId).stat30min), -1, FIND_BY_KEY(appVars.campaignsAppVar, "campaignId", m.campaignId).stat30min)

I’m wondering whether there’s a way to make this formula handle the addition and deletion of properties.

Any modification to the appVar objects would necessitate revising this formula because all of the properties are stated in the formula.

One formula isn’t horrible, but I’ll have a lot in my program, and I can already see the update nightmare looming when the API changes or users request additional or removed data characteristics.

Is there a solution for this dilemma?

I am glad that you are on the right path with this task at least. As far as I know variable schemas are pretty rigid. You can always update the data variables schema from the test tab in the rest configurator menu. But I am not sure if that is this easy in an app variable… :cry: