0

I am looking to access nested JSON data from a firebase database to use within a listView, this is something I have applied throughout my app, but am now having trouble having to access children of the data with dynamic properties.

An export of my JSON data from my data base is;

{
    "T&G Canary Wharf" : {
        "Administrator" : {
            "1550633367665" : {
                "date" : "2019-02-12T12:00:00.000",
                "details" : "Full Day",
                "name" : "Edward Lawrence",
                "status" : "pending"
            },
            "1550633370715" : {
                "date" : "2019-02-13T12:00:00.000",
                "details" : "Full Day",
                "name" : "Edward Lawrence",
                "status" : false
            },
            "1550845072137" : {
                "date" : "2019-02-12T12:00:00.000",
                "details" : "Full Day",
                "name" : "Katie Prescott ",
                "status" : 1
            },
        },
        "Stylist" : {
            "1551222170677" : {
            "date" : "2019-02-19T12:00:00.000",
            "details" : "Full Day",
            "name" : "Stylist Stylist",
            "status" : "pending"
      }
    }
  }
}

Per user of the app, group (in the above example T&G Canary Wharf) will always be set, but the subgroup (in the example Administrator & Stylists) is dynamic for admins, and this is where I am struggling,

My code for my firebase database read is below:

I am using felgo(formerly v-play), a link to their firebase documentation is:

Felgo Firebase Plugin

App {

    property var adminModel: []
    property var groupName //the group name is assigned onLoggedIn, in this example group name === T&G Canary Wharf

    FirebaseDatabase {
        onLoggedIn: { 
        firebaseDb.getValue("groups" + "/" + groupName, {
                                orderByValue: true
                            }, function(success, key, value) {
                            if(success){
                            console.log("ADMIN MODEL: " + JSON.stringify(value))
                            adminModel = value // my array where I intend to push the data too                              
                            }
                        })
                    }
                }
            }

I have been reading through;

access/process nested objects, arrays or JSON

(super helpful by the way) specifically the section of What if the property names are dynamic and I don't know them beforehand?

I can create two list entries, of Administrator and Stylist (the subGroups, but where the child key of this is also dynamic (the time the entry is created, e.g: "1550633367665"), I cannot seem to get further?

to create this model I have the code:

ListPage {
    id: adminPage

    model: Object.keys(adminModel)

delegate: SwipeOptionsContainer {
    id: container

    rightOption:  SwipeButton {
        anchors.fill: parent
        backgroundColor: "red"
        icon: IconType.trash

        onClicked: {
            container.hideOptions()
        }
    }

    SimpleRow {
        id: userRow
        width: parent.width
        text: modelData
        }
    }
}

My question is

How can I create a listView with the delegates being any object containing a "status" : "pending" - done in other areas using a loop of if (value[i].status === pending) { arr.push({...})}, but whilst the subgroup (Stylist/Administrator) is unknown, from the above database example there would be 2 list elements, but in reality will contain many more with multiple subGroup's.

Ldweller
  • 327
  • 2
  • 16
  • 1
    Instead of describing your code, show us the [minimal actual code that reproduces what you're struggling with](http://stackoverflow.com/help/mcve). That makes it much more likely that someone can and will help. See [how to create a minimal, complete, verifiable example](http://stackoverflow.com/help/mcve) for more hints on why this is useful, and how to increase your chances even furter. – Frank van Puffelen Feb 28 '19 at 03:40
  • Also note that it'll be easier to help if you include the actual JSON (as text, no screenshots). You can get this by clicking the "Export JSON" link in the overflow menu (⠇) on your [Firebase Database console](https://console.firebase.google.com/project/_/database/data). – Frank van Puffelen Feb 28 '19 at 03:41
  • @FrankvanPuffelen Hi Frank, thanks for the feedback and answer below, I have updated my answer with a JSON extract of my database and also with my code for reading from firebase for better context, let me know if you need anything else, thanks! – Ldweller Feb 28 '19 at 20:35
  • I'm a bit lost on what library you use to access Firebase. What is `firebaseDb.getValue(...`? – Frank van Puffelen Mar 01 '19 at 04:11
  • Hi @FrankvanPuffelen I am working with felgo(formerly v-play) i have updated my question with a link to thier documentation on firebase! Thanks – Ldweller Mar 01 '19 at 12:33
  • As Frank's stated in his first comment, a [mcve] would be incredibly helpful (both for you and us). Further comments (note that I'm unfamiliar with Felgo's Firebase Plugin): 1) What is `adminModel`? 2) What are subgroups? Not explicitly mentioned, but I'm guessing the Adminstrator/Stylist sort of roles? 3) You haven't yet shown us the code for "applying Object.keys... I create two list entries...". That might be a good starting point. 4) "_How can I create a listView of only pending items_" Specifically, what do you mean by "_items_"? – TrebledJ Mar 03 '19 at 15:15
  • 1
    Hi @TrebuchetMS I have updated my comment with the `ListPage` code for my `Object.keys`, sorry for the lack of clarification, when I know the direct key of the database I can create arrays for models, but it's accessing the children of dynamic paths i'm struggling with, let me know if you need more info! (Hopefully I've given enough) Thanks – Ldweller Mar 03 '19 at 15:38

2 Answers2

1

After doing getValue from FireBase, it seems like you need to perform a few things:

  1. Retrieve the subgroups from your group.
  2. Iterate through the subgroups.
  3. For each subgroup, retrieve the time entries.
  4. Filter the time entries based on whether their status is "pending".

It looks like you've already achieved Step 1 with Object.keys(adminModel). Now we'll take that a couple steps further with a for-loop (Step 2 √).

var subgroups = Object.keys(adminModel);
for (var i in subgroups) {
    var subgroup = adminModel[subgroups[i]];

    // ...
}

For convenience, we've defined subgroup_obj which will store the data of a subgroup. E.g.

"Stylist": {
      "1551222170677" : {
           "date" : "2019-02-19T12:00:00.000",
           "details" : "Full Day",
           "name" : "Stylist Stylist",
           "status" : "pending"
      }
}

We then go on to Step 3, retrieving time entries by again using Object.keys() but this time on the subgroup.

var timeEntries = Object.keys(subgroup);

Since Object.keys() returns an array, we can accomplish Step 4 by using the filter() array method to filter entries with a pending status.

var filteredEntries = timeEntries.filter(function(t) { return subgroup[t].status === "pending"; } );

With newer version of JS, you could do timeEntries.filter(t => subgroup[t].status === "pending") but this doesn't seem to be fully supported by Qt yet.

And that's that. filteredEntries gives us an array of time entries (e.g. [ "1551222170677" ]) for each subgroup.

If you want the complete time entry object, you could use the map array method to get

var filteredEntries2 = filteredEntries.map(function(t) { return subgroup[t]; });

which gives you an array of objects. So something like

[
{
    date: "2019-02-19T12:00:00.000"
    details: "Full Day"
    name: "Stylist Stylist"
    status: "pending"
}
]

Hope this helps!

TrebledJ
  • 8,713
  • 7
  • 26
  • 48
0

When you get data from the Firebase Database, you get back DataSnapshot that contains a forEach method which you can use to loop over all child nodes.

So to load a group and show the names of all items:

firebase.database().ref("group").once("value").then(function(snapshot) {
  snapshot.forEach(function(groupSnapshot) {
    groupSnapshot.forEach(function(subgroupSnapshot) {
      console.log(subgroupSnapshot.val().name);
    })
  })
})
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807