Firebase $id from second level Object

左心房为你撑大大i 提交于 2019-12-05 18:17:02

tl;dr - In Firebase it is ideal to have a flat data structure.

JSBin Example

In your case you have invoices nested under clients.

{
   "clients": {
      "1": {
         "name": "Alison",
         "invoices": {
            "0001": {
              "amount": 500
              "paid": true
            }
         }
      }
   }
}

This feels natural because the invoices are nicely grouped underneath the proper client. However, this can lead to bad performance in syncing data with Firebase. Firebase reads all data underneath a node.

This means every time you read /clients/1 you also get the invoices downloaded over the network. Even if you just need the client's name, you'll also get the the invoices.

The solution is to flatten your data structure.

{
   "clients": {
      "1": {
        "name": "Alison"
      }
   },
   "clientInvoices": {
     "1": {
        "0001": {
          "amount": 500
          "paid": true
        }
     }
   }
}

The important part to grasp here is the shared key.

In this example the key is 1. This is for simplicity. In reality you'll likely use a .push() id.

By using this pattern you'll still be able to retrieve all of the invoices for the client by simply knowing their key. This also decouples the client from the invoices.

As an added benefit your controller code and ng-repeat will be much easier.

In your case you should switch from a $firebaseObject to a $firebaseArray for the invoices. We can even create a helper factory that gets the invoices by a client's id.

.factory('invoices', function(fbUrl, $firebaseArray) {
   return function(clientId) {
      var ref = new Firebase(fbUrl).child('clientInvoices').child(clientId);
      return $firebaseArray(ref);
   }
})

// While we're at it, lets create a helper factory for retrieving a
// client by their id
.factory('clients', function(fbUrl, $firebaseObject) {
    return function(clientId) {
       var ref = new Firebase(fbUrl).child('clients').child(clientId);
       return $firebaseObject(ref);
    }
})

Now inject the helper factories into your controller and use the $routeParams.id to retrieve the client's invoices:

.controller('singleClientController', function($scope, $routeParams, invoices, clients) {

    $scope.client = clients($routeParams.id);
    $scope.clientInvoices = invoices($routeParams.id);

})

Now binding it to your template is a breeze:

<tr ng-repeat="invoice in clientInvoices">
     <td>
         <a href="#/invoices/details/{{invoice.$id}}/{{client.$id}}">
            {{invoice.settings.number}}
         </a>
     </td>
     ...
</tr>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!