How to add data to app variable?

Hi,

I am trying to build an app for a book.

I created a client side storage resource id. Then I created an app variable of type String.

Now I want to populate the contents of the book so that when the user opens the app, on the first screen, they see a list of all the chapters as a repeating array. How do I do this?

When the tap on any of the chapters, the lines open up. When the tap on any of the lines, the sublines open up etc.

This is what it should look like:

Book name
        Chapter 1
                 Line 1
                        Subline 1
                                Sub-subline 1
                        Subline 2
                                Sub-subline 2
                 Line 2
                        Subline 1
                                Sub-subline 1
                        Subline 2
                                Sub-subline 2

        Chapter 2
                 Line 1
                        Subline 1
                                Sub-subline 1
                        Subline 2
                                Sub-subline 2
                 Line 2
                        Subline 1
                                Sub-subline 1
                        Subline 2
                                Sub-subline 2

Thank you

The issue with client side storage is that there’s currently no good way to populate it with default data when the app launches, so your best bet now would be to define the structure as nested JSON.

You would first need to define an app variable with the correct schema:

Then, add a JavaScript node on your homepage Page mounted event to populate the data:

You can duplicate the whole schema to the chapters output, but you can also just use a formula with Set app variable:

Now, you can just set your home page list item to repeat based on appVars.chapters, and then open a page where you pass in current.chapterId as a parameter.

On the target page, you can then use a formula to look up the correct lines array:

LOOKUP(FIND(appVars.chapters, item.chapterId === params.chapterId), "lines")

You’d then continue to pass on chapterId and lineId params etc as you progress – on the final level, you’d have:

LOOKUP(FIND<subline>(LOOKUP(FIND<line>(LOOKUP(FIND<chapter>(appVars.chapters, chapter.chapterId === params.chapterId), "lines"), line.lineId === params.lineId), "sublines"), subline.sublineId === params.sublineId), "subSublines")

The code in the JavaScript node for your copypaste convenience:

const chapters = [
  {
    chapterId: "1",
    chapterName: "Chapter 1",
    lines: [
      {
        lineId: "1-1",
        lineName: "Line 1",
        sublines: [
          {
            sublineId: "1-1-1",
            sublineName: "Subline 1",
            subSublines: [
              {
                subSublineId: "1-1-1-1",
                subSublineName: "Sub-Subline 1"
              }
            ]
          }
        ]
      }
    ]
  }
]

return { chapters };

@Harri_Sarsa

Thank you for your prompt reply.

So the book is available as an XML which has the chapters, and the lines. What would be the best method to upload it to Apgyver?

As for the sublines and the sub-sublines, they are to be gradually added, line by line.

In your opinion, what would be the best way to do this?

Should I upload the whole book into Airtable and then do an API call to Appgyver? The sublines and sub-sublines would be updated in Airtable and hence updated in Appgyver?

Or should I (if possible) upload the book which is in XML format directly into Appgyver and there is another method to update the sublines and the sub-sublines?

Also, where can I find ‘Page mounted’?

Thank you!

Airtable would probably be a more straightforward way to manage the data than “hardcoding” it into the app logic itself like that – so if the app doesn’t have to be 100% offline, I’d go with that, as then you can also update things based on

Composer currently doesn’t have anything built-in to handle XML data, but if you Google “Convert XML to JSON”, there are a lot of tools you can find.

Page mounted is available on the page logic canvas, available when you select the page itself and click the “Add logic” button.

@Harri_Sarsa, thank you for your reply.

So I converted the XML to CSV and imported to airtable and setup a data API REST call to my app :slight_smile:

Then in the composure, I added a list item that is repeating by chapter name.

  • How can I order the repeating list by chapter number? So the chapter number is a column in the airtable database and another column is the chapter name.

  • I am also having issues with the AppGyver app on my iPhone. When I open the app I created, the spinner keeps spinning and nothing shows. I tried to leave it for a very long time and no luck. This however loads up on the web preview to show about 10 of the 114 chapters and still have a forever spinning spinner.

  • Do I still need to do anything with the Page mounted logic?

Thanks.
Sent you a LI request btw :slight_smile:

Are you running the Hide spinner flow function in the page mounted logic?

You can use the SORT_BY_KEY function on your data variable, so instead of binding data.Chapters or whatever you have, you’d bind the Repeat with property to

SORT_BY_KEY(data.Chapters, "chapterNumber")

Assuming your chapter number is stored under the chapterNumber key.

@Harri_Sarsa,

Thanks for the reply.

  • I set the ‘Repeat with’ to be a formula where I entered :

SORT_BY_KEY(data.Chapters, "_index")

That is giving an error as in the app is not saving.

Chapters is a column in the airtable spreadsheet and so is _index

I tried

SORT_BY_KEY(data.Chapters, "data.Chapters._index")

and still giving an error.

  • I clicked on my page and ‘Add logic to Main page’ and it is all emp;ty. There is no page mounted logic.

Thanks.

So you are able to set the formula and it doesn’t complain, but clicking Save gives an error? Were you able to get around this – could I try to repro this by looking at your app, if you give me the app ID?

For the Page mounted event, sounds like you accidentally removed it – what you can do is drag in the Receive event node from the component library and choose Page mounted from the event dropdown (you need to do this twice now due to https://tracker.appgyver.com/bug-reports/p/quirky-behavior-of-receive-event-node).