我是firebase和angularjs的新手。对于我的销售应用程序,我想同时使用它们。所以,在我的应用程序中,我使用 AngularJS v1.5.8 + Firebase v3.3.0 + AngularFire 2.0.2 。我在firebase数据库中有销售和用户对象,并且有一个业务逻辑,一个用户可以销售多个产品,但一个产品只能有一个所有者(用户)。
以下是数据库中的用户和销售对象:
{
"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" : "burak.kahraman@gmail.com",
"name" : "Burak Hero",
"nick" : "Burak'in Mutfagi"
},
"-KQ52OJd-lwoDIWzfYFT" : {
"address" : "Izmir kaynaklar",
"email" : "ayse@gmail.com",
"name" : "Ayse Kahraman",
"nick" : "Ayse'nin Mutfagi"
}
}
}
我想要做的是,当我的应用程序打开时,它会显示所有销售以及相应的用户详细信息。 (就像letgo应用程序的主页一样)这意味着我应该在销售和用户对象之间实现简单的连接。据我在互联网和api文档中搜索,没有办法在一次调用firebase时实现这种连接。 (如果我错了,请纠正我)所以我使用下面的方法在 SalesService 中使用 $ loaded 函数来实现连接。
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;
};
});
如您所见,我正在获取所有销售,在完成后,循环每次销售以通过调用下面显示的另一个 UsersService 获取并设置相关的用户详细信息
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;
};
});
到目前为止一切顺利,当我在我的Controller中调用 SalesService.getAllSalesJoin 函数并使用<pre>{{$ctrl.allSales | json}}</pre>
打印JSON对象时,一切都按照我的意愿工作,下面是Controller代码并打印模板中的JSON对象。
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();
}]
});
模板显示合并的对象
{
"$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": "ayse@gmail.com",
"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": "burak.kahraman@gmail.com",
"name": "Burak Hero",
"nick": "Burak'in Mutfagi"
}
},
.....
但是问题是,当更改服务器数据(输入新销售或删除旧销售)时,angular会自动理解更改,但会将更改应用于视图而不实现或调用我的加入函数,它只打印仅销售对象而不是与用户合并的销售对象。下面是服务器数据更改后的显示对象。
{
"$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"
},
....
我很困惑,为什么它表现得那样?我的方法是使用 $ loaded 错误实现连接吗?或者我应该使用另一种方法来实现这种连接?我期待着看到你无价的建议和想法。
答案 0 :(得分:0)
$loaded()
仅在加载初始数据时触发。来自reference documentation(强调我的):
返回从数据库下载初始对象数据后解析的承诺。
这是我经常说的主要原因:&#34;如果你正在使用$loaded()
,那么你做错了&#34;。
您需要通过多次通话加入数据。在AngularFire中,您可以extend $firebaseArray
执行此类操作。有关如何执行此操作的一个很好的示例,请参阅加藤的这个答案:Joining data between paths based on id using AngularFire
答案 1 :(得分:0)
感谢指南@Frank。我阅读了你的所有建议并找到了解决方案。为了提供stackoverflow知识并在这里帮助其他人是问题的完整解决方案。
我首先创建了一个新工厂,扩展$ firebaseArray并覆盖$$ added和$$更新方法,以便在每次更新或添加数据时对Users对象执行 join 。
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;
});
如您所见, SalesFactory 使用另一个名为销售的工厂。在该特定工厂中,我检索Sales对象的所有属性,并将它们分配给相应的属性。这就是我通过创建新属性来连接到Users对象的情况: this.userObj 缺少一件事就是调用新的Factory而不是$ firebaseArray
this.getAllSalesArray = function () {
var sales;
var refSales = firebase.database().ref('sales');
sales = SalesFactory(refSales);
return sales;
};
总而言之,与相关用户一起加入的所有Sales对象都打印到视图中,
[
{
"$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": "ayse@gmail.com",
"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": "burak.kahraman@gmail.com",
"name": "Burak Hero",
"nick": "Burak'ın Mutfağı"
}
},
...
]