handling nested JSON data for ListView

201 Views Asked by At

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.

2

There are 2 best solutions below

0
TrebledJ On BEST ANSWER

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!

0
Frank van Puffelen On

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);
    })
  })
})