2016-09-22 3 views
1

Ich bin neu bei Firebase und angularjs. Für meine Verkaufsanwendung möchte ich beide verwenden. Also, in meiner App verwende ich AngularJS v1.5.8 + Firebase v3.3.0 + AngularFire 2.0.2. Ich habe Verkaufs- und Benutzerobjekte in Firebase db und hat eine Geschäftslogik, dass ein Benutzer mehrere Produkte verkaufen kann, aber ein Produkt kann nur einen Besitzer (Benutzer) haben.

Hier sind die Benutzer und Verkäufe Objekte in der Datenbank:

{ 
    "sales" : { 
    "-KQlb5N6A9rclc5qcWGD" : { 
     "price" : 8, 
     "quantity" : { 
     "count" : 12, 
     "type" : "porsiyon" 
     }, 
     "status" : "sale", 
     "title" : "Patlicanli Borek", 
     "user" : "-KQ52OJd-lwoDIWzfYFT" 
    }, 
    "-KQlcScsq8cidk7Drs04" : { 
     "price" : 12, 
     "quantity" : { 
     "count" : 10, 
     "type" : "porsiyon" 
     }, 
     "status" : "sale", 
     "title" : "Deneme", 
     "user" : "-KQ5-mZBt6MhYy401gGM" 
    }, 
    "-KQzXHwOv2rC73scjV46" : { 
     "price" : 12, 
     "quantity" : { 
     "count" : 11, 
     "type" : "porsiyon" 
     }, 
     "status" : "sale", 
     "title" : "Pacanga", 
     "user" : "-KQ5-mZBt6MhYy401gGM" 
    }, 
    "-KSCBgpArtnKunUuEuVr" : { 
     "price" : 15, 
     "quantity" : { 
     "count" : 15, 
     "type" : "porsiyon" 
     }, 
     "status" : "sale", 
     "title" : "Iskembe", 
     "user" : "-KQ52OJd-lwoDIWzfYFT" 
    } 
    }, 
    "users" : { 
    "-KQ5-mZBt6MhYy401gGM" : { 
     "address" : "Halkali kucukcekmece", 
     "email" : "[email protected]", 
     "name" : "Burak Hero", 
     "nick" : "Burak'in Mutfagi" 
    }, 
    "-KQ52OJd-lwoDIWzfYFT" : { 
     "address" : "Izmir kaynaklar", 
     "email" : "[email protected]", 
     "name" : "Ayse Kahraman", 
     "nick" : "Ayse'nin Mutfagi" 
    } 
    } 
} 

Was ich tun möchte, ist, wenn mein app geöffnet ist, es alle Verkäufe zusammen mit entsprechenden Benutzerdaten zeigen. (genau wie Hauptseite von letgo Anwendung) Was bedeutet, dass ich eine einfache Verbindung zwischen Verkauf und Benutzer Objekte implementieren sollte. Soweit ich Internet und API-Dokumente durchsucht habe, gibt es keine Möglichkeit, diese Art von Join in einem einzigen Aufruf an Firebase zu implementieren. (Pl korrigieren Sie mich, wenn ich falsch liege) So verwendete ich unten Methode mit $ geladen Funktion innerhalb meiner SalesService zu implementieren beitreten.

angular. 
    module('core.sales') 
    .service('SalesService', function ($firebaseArray, $firebaseObject, UsersService) { 
this.getAllSalesJoin = function() { 
     var sales; 
     var refSales = firebase.database().ref('sales'); 
     sales = $firebaseObject(refSales); 
     sales.$loaded() 
     .then(function() { 
      angular.forEach(sales, function (sale) { 
      var saleUser = UsersService.getUserDetail(sale.user); 
      saleUser.$loaded() 
       .then(function() { 
       sale.user = saleUser; 
       }); 
      }); 
     }); 
     return sales; 
    }; 
}); 

Wie Sie sehe ich alle Verkäufe bin holen, nachdem sie beendet wurde, für jeden Verkauf Looping Benutzer Detail zu bekommen und Satz im Zusammenhang mit einem anderen UsersService Aufruf unter

angular. 
    module('core.users') 
    .service('UsersService', function ($firebaseArray,$firebaseObject) { 
this.getUserDetail = function (userId) { 
     var user; 
     var refUser = firebase.database().ref('users/'+userId); 
     user = $firebaseObject(refUser); 
     return user; 
    }; 
    }); 

weit, so gut So gezeigt , wenn ich SalesService.getAllSalesJoin Funktion in meinem Controller aufrufen und das JSON-Objekt mit <pre>{{$ctrl.allSales | json}}</pre> drucken, funktioniert alles wie ich wollte, unten ist der Controller-Code und JSON-Objekt in der Vorlage gedruckt.

angular. 
    module('saleList'). 
    component('saleList', { 
    templateUrl: 'MCTs/sale-list/sale-list-template.html', 
    controller: ['SalesService','UsersService', function SaleListController(SalesService,UsersService,$scope) { 

      this.allSales = SalesService.getAllSalesJoin(); 
}] 
    }); 

Vorlage zeigt die fusionierte Objekte

{ 
    "$id": "sales", 
    "$priority": null, 
    "-KQlb5N6A9rclc5qcWGD": { 
    "price": 8, 
    "quantity": { 
     "count": 12, 
     "type": "porsiyon" 
    }, 
    "status": "sale", 
    "title": "Patlicanli Borek", 
    "user": { 
     "$id": "-KQ52OJd-lwoDIWzfYFT", 
     "$priority": null, 
     "address": "Izmir kaynaklar", 
     "email": "[email protected]", 
     "name": "Ayse Kahraman", 
     "nick": "Ayse'nin Mutfagi" 
    } 
    }, 
    "-KQlcScsq8cidk7Drs04": { 
    "price": 12, 
    "quantity": { 
     "count": 10, 
     "type": "porsiyon" 
    }, 
    "status": "sale", 
    "title": "Deneme", 
    "user": { 
     "$id": "-KQ5-mZBt6MhYy401gGM", 
     "$priority": null, 
     "address": "Halkali kucukcekmece", 
     "email": "[email protected]", 
     "name": "Burak Hero", 
     "nick": "Burak'in Mutfagi" 
    } 
    }, 
..... 

Aber das Problem ist, wenn Server-Daten geändert wird (neu Verkauf eingegeben oder alte gelöscht wird), versteht Winkel automatisch die Änderung aber es wendet die Änderung auf die Ansicht an, ohne meine verknüpfte Funktion zu implementieren oder aufzurufen, druckt einfach nur das Verkaufsobjekt nicht das fusionierte mit Benutzern. Das folgende Objekt wird angezeigt, nachdem die Serverdaten geändert wurden.

{ 
    "$id": "sales", 
    "$priority": null, 
    "-KQlb5N6A9rclc5qcWGD": { 
    "price": 8, 
    "quantity": { 
     "count": 12, 
     "type": "porsiyon" 
    }, 
    "status": "sale", 
    "title": "Patlicanli Borek", 
    "user": "-KQ52OJd-lwoDIWzfYFT" 
    }, 
    "-KQlcScsq8cidk7Drs04": { 
    "price": 12, 
    "quantity": { 
     "count": 10, 
     "type": "porsiyon" 
    }, 
    "status": "sale", 
    "title": "Deneme", 
    "user": "-KQ5-mZBt6MhYy401gGM" 
    }, 
.... 

Ich bin verwirrt, warum es so verhält? Ist mein Weg zu implementieren Join mit $ loaded falsch? Oder sollte ich eine andere Methode verwenden, um diese Art von Join zu implementieren? Ich freue mich auf Ihre wertvollen Vorschläge und Ideen.

Antwort

0

Vielen Dank für den Leitfaden @Frank. Ich habe alle deine Vorschläge gelesen und die Lösung gefunden. Um Stackflow-Wissen zu vermitteln und anderen zu helfen, gibt es die komplette Lösung für das Problem.

Zuerst erstellte ich eine neue Factory, die $ firebaseArray erweitert und die $$ addierten und $$ aktualisierten Methoden überschreibt, um Join zu Benutzerobjekt jedes Mal durchzuführen, wenn die Daten aktualisiert oder hinzugefügt werden.

angular. 
    module('core.sales').factory("SalesFactory", function ($firebaseArray, Sales) { 
    return $firebaseArray.$extend({ 
     $$added: function (snap) { 
     return new Sales(snap); 
     }, 

     $$updated: function (snap) { 
     return this.$getRecord(snap.key).update(snap); 
     } 

    }); 
    }); 

angular. 
    module('core.sales').factory("Sales", function ($firebaseArray, $firebaseObject) { 
    var refUsers = firebase.database().ref('users'); 

    function Sales(snapshot) { 
     this.$id = snapshot.key; 

     this.update(snapshot); 
    } 

    Sales.prototype = { 
     update: function (snapshot) { 
     var oldTitle = angular.extend({}, this.title); 
     var oldPrice = angular.extend({}, this.price); 
     var oldQuantity = angular.extend({}, this.quantity); 

     this.userId = snapshot.val().user; 
     this.title = snapshot.val().title; 
     this.status = snapshot.val().status; 
     this.price = snapshot.val().price; 
     this.quantity = snapshot.val().quantity; 
     this.userObj = $firebaseObject(refUsers.child(this.userId)); 

     if (oldTitle == this.title && oldPrice == this.price && 
     oldQuantity.count == this.quantity.count && oldQuantity.type == this.quantity.type) 
      return false; 
     return true; 

     }, 

    }; 

    return Sales; 
    }); 

Wie Sie sehen, SalesFactory verwendet eine andere Fabrik Umsatz genannt. In dieser bestimmten Factory lade ich alle Eigenschaften des Verkaufsobjekts ab und ordne jeden dieser Objekte der entsprechenden Eigenschaft zu. Und das ist der Fall, dass ich an Benutzer beitreten am Ausführen Objekt durch neue Eigenschaft zu erstellen: this.userObj Eine Sache fehlt, dass nur wird die neue Fabrik Aufruf statt firebaseArray $

this.getAllSalesArray = function() { 
     var sales; 
     var refSales = firebase.database().ref('sales'); 
     sales = SalesFactory(refSales); 
     return sales; 
    }; 

Alles in allem, alle Das Verkaufsobjekt, das mit dem zugehörigen Benutzer verknüpft ist, wird in die Ansicht

[ 
    { 
    "$id": "-KQlb5N6A9rclc5qcWGD", 
    "userId": "-KQ52OJd-lwoDIWzfYFT", 
    "title": "Patlicanli Borek", 
    "status": "sale", 
    "price": 12, 
    "quantity": { 
     "count": 11, 
     "type": "tabak" 
    }, 
    "userObj": { 
     "$id": "-KQ52OJd-lwoDIWzfYFT", 
     "$priority": null, 
     "address": "İzmir kaynaklar", 
     "email": "[email protected]", 
     "name": "Ayşe Kahraman", 
     "nick": "Ayşe'nin Mutfağı" 
    } 
    }, 
    { 
    "$id": "-KQlcScsq8cidk7Drs04", 
    "userId": "-KQ5-mZBt6MhYy401gGM", 
    "title": "Deneme", 
    "status": "sale", 
    "price": 12, 
    "quantity": { 
     "count": 10, 
     "type": "porsiyon" 
    }, 
    "userObj": { 
     "$id": "-KQ5-mZBt6MhYy401gGM", 
     "$priority": null, 
     "address": "Halkalı küçükçekmece", 
     "email": "[email protected]", 
     "name": "Burak Hero", 
     "nick": "Burak'ın Mutfağı" 
    } 
    }, 
... 
] 
gedruckt
0

$loaded() wird nur ausgelöst, wenn die Anfangsdaten geladen wurden. Vom reference documentation (Hervorhebung von mir):

Gibt ein Versprechen, das aufgelöst wird, wenn die anfänglichen Objektdaten aus der Datenbank heruntergeladen.

Dies ist der Hauptgrund, warum ich oft sage: "Wenn Sie $loaded() verwenden, machen Sie es falsch".

Sie haben recht, wenn Sie Daten mit mehreren Anrufen verbinden müssen. In AngularFire können Sie extend $firebaseArray eine solche Operation durchführen. Für ein gutes Beispiel, wie dies zu tun ist, finden Sie diese Antwort von Kato: Joining data between paths based on id using AngularFire

Verwandte Themen