我正在尝试将Firebase和AngularFire用于我正在构建的应用程序。诚然,我是 angular 和 Firebase 的新手,所以任何帮助将不胜感激。
我在Firebase中有以下数据库结构:
- 史诗
- 史诗 1
- 编号
- 标题等
- 史诗2
- 编号
- 标题等
- 史诗 1
-
用户
-
用户 1
-活性史诗
-
活跃史诗 1
-
活跃的史诗2
-
-
在下一页上,我对数据库中的每个史诗都有一个ng重复。每个史诗都有一排按钮,其中一个给我带来了麻烦。如果当前用户已经启动了长篇故事(例如,长篇故事出现在该用户的"活动史诗"中),那么按钮应该显示"点击退出"。如果长篇故事不在用户的活动史诗中,则它应显示"开始"。
单击按钮时应执行不同的操作,具体取决于按钮标签。因此,如果按钮标签显示"开始",则应用应将长篇故事添加到当前用户的"活动史诗"中,并将按钮标签更改为"点击退出"。相反,如果按钮标签为"点击退出",则应用应从"活动史诗"中删除长篇故事,并将按钮标签更改回"开始"。
但是,我得到了各种奇怪的行为。当我使用虚拟 ID (例如 1 或 0)时,该应用程序会显示正确的按钮标签。但是,当我添加带有 Firebase 生成 ID 的长篇故事时,所有标签都会重置为"开始"。我还注意到该应用程序正在多次循环浏览每个史诗(我为显示的每个史诗进入了调试控制台.log)。
我认为问题可能是将Firebase数据绑定到$scope后我有多个承诺对象。如果可以的话,请帮忙!
这是代码:
视图
<div ng-repeat="(name,epic) in epics | filter:search | orderBy:order | filter:{category:category}" class="epic">
<div>
<div class="small-block-grid-3 epicActions">
<li><a href="#"> Remix </a></li>
<li><a href="#/share"> Share </a></li>
<li><a href="#" ng-click="handleLabel(name)" prevent> {{getLabel(name)}} </a></li>
</div>
</ul>
</div>
</div>
控制器
$scope.desiredUser = UserService.getCurrentUser();
var ref = new Firebase("https://epicly.firebaseio.com/epics");
angularFire(ref, $scope, 'epics');
var ref2 = new Firebase("https://epicly.firebaseio.com/users");
angularFire(ref2, $scope, 'users').then(function(){
for (var i = 0; i<$scope.users.length; i++){
if($scope.users[i].email === $scope.desiredUser){
$scope.currUser = $scope.users[i];
}
}
var ref3 = new Firebase("https://epicly.firebaseio.com/users/" + $scope.currUser.id + "/activeepics");
angularFire(ref3, $scope, 'activeEpics').then(function(){
console.log($scope.activeEpics);
$scope.getLabel = function(epic){
console.log(epic);
for(var i = 0; i < $scope.activeEpics.length; i++){
if ($scope.activeEpics[i].id === epic) {
return "Tap Out";
}
}
return "Start";
}
$scope.handleLabel = function(name){
var label = $scope.getLabel(name);
if(label === "Tap Out"){
//remove from active epics
} else {
//add to activeepics
$scope.toAdd = {"id": name}
$scope.activeEpics.push($scope.toAdd);
}
}
});
});
首先回答您的直接问题:
-
为什么添加
epic
时所有标签都重置为"Start"
?您的
$scope.getLabel
方法是尝试遍历$scope.activeEpics
,这是angularFire
承诺的结果。但是$scope.activeEpics
是一个对象,而不是一个数组,所以它没有索引或.length
属性。即使有,假设的结果数组元素也不会具有您期望的id
属性。相反,您正在寻找activeEpic
引用的name()
,以与epic
引用的name()
进行比较。这实际上简化了您的生活,因为您只想知道activeEpics
对象中是否存在给定的epic
名称,因此该方法可能如下所示:$scope.getLabel = function(epicName){ var labelText = $scope.activeEpics[epicName] ? "Tap Out" : "Start"; return labelText; }
就目前而言,您的迭代没有运行,一切都会恢复到
"Start"
。 -
为什么您的
$scope.getLabel
函数执行这么多次?这是 AngularJS 监视系统的一个函数,因为您的视图正在调用一个方法,然后更改视图,因此手表再次运行,再次触发该方法(粗略地说),依此类推,对于所有需要标签的史诗。请参阅此SO答案以获取更好的解释。
如果我可以提供一些一般性建议,看起来您正在尝试以某种迂回的方式通过他们的电子邮件找到用户。您可以尝试使用 Firebase 优先级系统更优雅地完成相同的操作,如此处所述。如果您收紧格式并全面使用更明确的变量和参数命名,那么遵循代码也会更容易。只有我的两分钱。祝你好运!
我认为您的部分问题可能是您正在尝试遍历一个对象,就好像它是一个数组一样。如果您使用连续的数字 ID(0、1 等)在 Firebase 中存储数据AngularFire会将您的数据视为一个数组。如果您使用键(例如使用 Firebase.push() 创建的键),AngularFire 会将您的数据视为键和值的字典。
我会提前指定您希望angularFire变量的数据类型,因此在调用AngularFire()
之前插入$scope.users = []
和$scope.activeEpics = {}
,或者任何情况,然后检查对象以查看它们实际上是字典还是数组,并适当地更改迭代方法。