I’ve a simple app that opens with a loading screen (logo & app details). This screen calls an API in the background and adds the response into a Data Variable and then opens a new page. This new page has no idea of the data. I don’t for the life of me seem to be able to pass the full object to the next page so I can do dataObject.Result.itemWanted in any formula.
You’d think I’d easily be able to call an API, save the data into a dataVariable and move onto another page and be able to reference that data.
I wanted to do exactly what you’re asking because I didn’t want to make another call to my server with an object id when my first call returned all the objects.
I just figured out a way to do it (I have less than a day experience in AppGyver so take it with a pinch of salt )
The challenged is that the Data and Page variables are available only on the page that they’re defined.
So what I did was to save the data into an App Variable then access the data from the app variable on the page that I require the data.
Here is a quick overview of how I did mine. Note that your setup will differ based on how your data is structured. But I’m guessing you data is a list of objects.
Create an app variable. Set the type to Array and the Array item type to “Any JSON-serializable value”
Go to the page where you have the Data Variables defined. Select the data variable. Then open the Logic editor at the bottom of the page. Add a new Set App Variable logic. Create a connection from the existing “Get record collection” to the Set App Variable component.
In the property editor for the App variable select your app variable defined in step 1 then set the value to “Get record collection/ Collection of records”. Save.
Finally go to the page where you want to display the data (I’m jumping the step where you pass the object id as a parameter to the page you want to display the data).
To pull a data from the App Variable you created use the Formula editor.
In my case i used the Array function FIND_BY_KEY (1) to get a specific object from my array (2). My array objects had a key called _id (3) and i passed the value for the key through a Parameter variable (4). Finally i retrieved the field value (5)
I know this is a bit complicated and I’m hoping there is a simpler way to do this.
That is essentially one way to do it – an alternative is to define e.g. a
currentRecord app variable with the same schema as the data variable, and then when you’re opening the page, set the app variable to
current instead of passing in an ID param.
We’ll be bringing in the ability to pass whole objects as params (there will be a size limit on web as params are being passed as query params, but maybe the solution will be to add a “Do not pass as query parameter on web” option that will then use the internal channel for this). Additionally, our new binding type selector (https://tracker.appgyver.com/feature-requests/p/updated-binding-type-selector-properties-panel) feature we’re working on will bring in schemas as first class citizen, so I can choose that my
currentRecord app variable schema is “Single record of data resource XXX” instead of having to manually copy it over.
Definitely want to make this use case simpler!
Interesting … thanks to both for different options - really appreciate that.
How to perform this? I cannot find this type of app variable
With the recent binding UI update, the namings were unified. You’ll find the options as List and Any value (instead of Array and Any JSON-serializable value)
Hi @Pekka_Aaltonen @Harri_Sarsa,
Is there a simpler way to pass data across pages to allow other pages to recognize properties i.e objectId?
Sorry I don’t understand, a simpler way than a page parameter, where you can pass e.g. objectId, which you can use to fetch the data? Please explain your usecase a little more
Hi Mevi, thank you for replying. I have already solved it. Great videos on youtube!
I haven’t found the way to pass an object as a page parameter, is this possible @Harri_Sarsa? In fact, it is quite a pain to pass something like a number variable as a parameter, since only text types are allowed, which means I must use formulas to convert the parameter (e.g. an integer text) before setting the page variable (e.g. number).
Hi! It isn’t possible to pass an Object as a page parameter. You should instead pass something like the id of what you want displayed instead. I can see the value in not having to convert number type page parameters to text and back again (however I think there was a technical reason why we only allow text type page parameters, probably related to web urls, if you’d like I can ask about that). If you really need to pass an Object, I have seen people use app variables for this purpose – but in general I would consider passing an id better practice.
Hi @Mevi! By id you mean the identifier of an object? It is a valid approach and one I already use. However, that means making an unnecessary call to the API to retrieve the object’s information unless caching is used, which isn’t the easiest thing to implement.
To illustrate my point, a very common scenario is to have a collection of objects fetched from a REST API that renders a list of components. When you click on each component another page with detailed information is shown. In this case, the object information is already present in the original array fetched from the API, so populating the details page should be as simple as just retrieving the element of the array with the corresponding id. However, since you cannot pass an object as a parameter you are left with two options instead:
Pass the object id and make another call to the API to retrieve the information about the object, which you already had. If you’re using a REST API and not something like GraphQL (which you can’t use with AppGyver), then this is wasteful. Making API calls to a production backend costs money.
Cache the initial collection into local storage, pass the object id, then load up the cache again within the new page and retrieve the object using the given id. This is the current approach I use, but it makes the logic a lot more complex and harder to manage. Also loading the cache each time you open a details page can decrease performance depending on the size of the cache.
Maybe I’m missing a third, more efficient approach, but as you can see, at least in some very common situations it would be much easier (and better practice in my opinion) to just pass an object with the data already fetched from an API.
We are agreed, it’s indeed wasteful to fetch the Object information again if you were able to fetch all the data in the Get All call (for some optimisation in very big calls, the amount of properties in Get All could be reduced to what’s necessary, and then fetch again on the details page, which would make more sense).
We mostly use saving the data into an app variable and then getting it from there, and doing most if not all of the fetching on global canvas instead of separate pages, so the fetch to the app variable is not done more often than needed.
In general we should definitely push towards making this easier or more intuitive for our users, but I don’t know of any plans for that yet
I just want to get some clarification. I am building an App and when you press “Run” I am making 20+ API calls, I was hoping to then navigate to other pages and display some of the data. However when I move pages the data variables are blanked?
Reading the above makes me think that I cannot just run my calls at once and use the data throughout the app. Could you confirm if that is the case ?
I don’t understand why you wouldn’t be able to use data variables across different pages. I don’t really want to trigger the individual API’s when going into the relevant page as if the user went back to the home screen , then back into said page it would trigger the API to run again ?!!
Hi. If you want to use data from one place across the app, do one of the following:
- Fetch the data once (on a page or on global canvas) and store it to an app variable
- Then either use it straight from the app variable or for each page, create a data variable to which you get the data from the app variable.
If you want to learn more about different types of variables, it might be helpful to check out these docs or these videos.
I found out a way how to make this work:
Create an Data Variable On Device Data Source with the same fields as your external API source
on the global convas create an IF(systemVars.networkStatus == “none”, false, true) so that if it is true it downloads the latest data via external API and updates the device database. if not, then you can give a message like ‘no connection, using device database’
Behind the true output, put Get_Record Collection, have that feed into a Set item to storage (you can give it any name)
Then on the pages where you need this data, add the on Data Variable device data resource (no need to add the external one). IMPORTANT: do not use get record collection and delay; you can delete those two. put behind page mounted: Get Item from stage and type the name you used in 3. Then have that flow into a variables ‘set data variable’ and put in data variable name for your device data variable and put in record collection a formula “outputs[“Get item from storage”].item”. Nothing else, ignore any error.
This works fine with me and just downloads the external databases at start only and then uses the on device storage in all the other apps. And if no connection it uses the last stored database.
Hi. I need to do this as well. Can you take me through this step by step? Thank you.
can you give more information on how you did this?
Hello everyone, i need help maybe something like that issue. I am just learning to build a simple QR Code Scanner App where I use a spreadsheet as a database. I have watched tutorials on youtube and it works but not really what I expected. The description of the app that I have run is that the app can scan the QR Code then match it with the database and display it on the same page, while what I want is something similar but the output data is not displayed on a different page. Thank you very much.