如何过滤掉或摆脱数组中的空对象? AngularJS,Firebase

时间:2014-08-05 15:54:27

标签: javascript arrays angularjs firebase angularfire

我的应用程序是使用AngularJS,Yeoman堆栈,连接到Firebase,AngularFire数据库构建的。在我的应用程序中,我正在尝试上传和删除图片,如下所示

enter image description here

它工作正常,除非我删除其他图像之间的任何imgs它实际上不删除img但用宽度和高度为0的img替换它...或者它似乎(更多信息在底部)

enter image description here

如果我删除另一个" in-bewteen" img同样的交易

enter image description here

只有当我删除最外层的img时,该页面才真正删除了imgs。

enter image description here

^^注意顶行上另外两个图像之间的图像是如何删除的,因为它是通过其他img对象水平包围的。我不得不使用firebase。将底部的两个img移除到我首先删除的那个的右边,然后才删除整个底行。

我不知道为什么我会收到这个错误,有人能给我一些反馈吗?

这是我的控制器中的deleteImg和updateImg函数

angular.module('myApp').controller('MainCtrl', ['$scope', '$firebase', '$filter', function($scope, $firebase, $filter) {
$scope.deleteImg = function(img) {
    if (confirm('Are you sure you want to delete the img?') === true) {
        var deletingID = img.id; 
        var deletingLink = fireRef + "/" + img.id;
        var deleteRef = new Firebase(deletingLink);
        deleteRef.remove();
        $(".delete").remove();
        location.reload();
    }
};

$scope.updateImg = function(Img) {
    if (confirm('Are you sure you want to update the Img?') === true) {
        var updatingID = $scope.selectedImg.id; 
        var updatingLink = fireRef + "/" + $scope.selectedImg.id;
        var updateRef = new Firebase(updatingLink);

        var dataObject = {
            "name" : $scope.selectedImg.name, "description": $scope.selectedImg.description, "type": $scope.selectedImg.type ... etc...
        };
        updateRef.set(dataObject);
        location.reload();
    }
};
}]);

以下是我实例化我的数组和Firebase数据库以及创建新的$ scope.selectedImg的方法。我目前正在从firebase数据库中获取数据并实例化Img对象数组。我在应用程序中使用该数组作为我的img模型。

var fireRef = new Firebase('MY_FIREBASE_URL');

$scope.imgs = []; //<<< instantiate a new array

var imgNum = 0;
var toArrayFirebaseLink = fireRef + '/' + imgNum;

fireRef.once('value', function(allSnapshot) {
    allSnapshot.forEach(function(imgSnapshot) {
        var i = imgSnapshot.child('id').val();
        if( i !== null ){
            // set databaseSnapshot to our img array
            $scope.imgs[i] = imgSnapshot.val();
        }
   });
});

$scope.instantiateImg = function(object) {
    $scope.selectedImg = {};
    // $scope.selectedImg.name = "";
    $scope.selectedImg.etc = "";
    $scope.selectedImg.etc = "";
};

//Created selectedImg with data retrieved from database to be used within the views.
$scope.selectImg = function(object) {
    $scope.selectedImg = object;
};

这是我的html视图

<div class="container">  
 <div class="col-xs-6 col-sm-4 col-md-4 col-lg-3 campaign-thumbs" ng-repeat="img in imgs track by $index" ng-animate="'animate'">

<button type="button" class="delete" ng-click="deleteImg(img)">
      <span>&times;</span>
      <span class="sr-only">Delete</span>
</button>

<img ng-click="selectImg(img)" src="{{img.imgSrc}}" class="img-responsive" data-toggle="modal" data-target="#imgModal">
  </div>
</div>

使用chrome AngularJS扩展我发现我使用firebase remove()函数在数据库中删除了元素,我的$ scope.imgs数组仍然有一个&#34; null&#34;我删除它的空间中的元素。见下图

enter image description here

如何解决此错误?


EDIT1: 我按照@ m.e.conroy的建议添加了拼接功能并认为它工作得很好,特别是因为我删除了location.reload()并且在视图中它显示图片被删除而没有刷新。但是,当我刷新页面时,同样的&#34;鬼&#34; imgs及其删除按钮再次出现。

当我检查范围模型的AngularJS chrome扩展时,它显示最外面的img(&#34之间的img;中间&#34; ghost imgs)正在接管已删除的图像,意味着删除的图像被设置为具有相同的名称,id和最外部img对象的其他属性。再一次,根据chrome扩展,阵列元素不会被移除,而只是被替换。一旦我刷新它然后回到我以前的&#34; null&#34;数组中的元素。这很奇怪,因为在我的Firebase仪表板中,它显示imgs确实被删除但是在删除最外层的img之前它不会反映在我的视图中。以下是我的Firebase信息中心和索引的视图。仅当删除img 24时,实际上才会应用更改。

enter image description here


EDIT2: 正如@katowulf在本文中所引用的那样(https://www.firebase.com/blog/2014-04-28-best-practices-arrays-in-firebase.html),我遇到了他在&#34;在数组中存储数据的好用例&#34;中描述的确切问题。部分。目前,我试图在我删除的每个imgs之后定位每个imgs,并将其ID更改为id - 1以及将火灾中的imgs位置改为firebar_url/ref - 1但我感觉像我试图强制实施而不是找到正确的解决方案。我应该尝试重构我的代码以利用他建议的对象吗? (我最初尝试过,但是我无法抓取对象,因此它的属性必须依靠firebase快照来实例化和创建我的数组。参考:How would I convert my new Object data I am retrieving from Firebase into the JSON form as I had before)。欢迎任何反馈。


我的解决方案:手动更改索引值以及相应的ID&#39;对于已删除的所有img对象,属性为-1。

$scope.deleteImg = function(index, img) {
    if (confirm('Are you sure you want to delete the Img?') === true) {
        $scope.imgs.splice(index,1); //remove objects in array

        var i; 
        for(i = index; i < $scope.imgs.length; i++) {
            //I want to grab the next img object 
            var previousIndexID = i; //start from the picture right after the one deleted and change its id to id-1
            var newIndexID = i+1;
            var previousIndexLink = fireRef + "/" + previousIndexID;
            var newIndexLink = fireRef + "/" + newIndexID;
            var previousIndexRef = new Firebase(previousIndexLink);
            var newIndexRef = new Firebase(newIndexLink);

            var idIndexLink = fireRef + "/" + previousIndexID + "/id";
            var idIndexRef = new Firebase(idIndexLink);

            console.log(previousIndexRef.toString()); // element[index] that got deleted
            console.log(newIndexRef.toString());      // element[index] next img object

            //copy the next img object into the location of the object that just got removed() 'url/num-1' and 'url/id' value 
            newIndexRef.once('value', function(snap) {
                var i = snap.val();
                previousIndexRef.set(i);
            });
            idIndexRef.once('value', function(snap) {
                var i = snap.val();
                idIndexRef.set(i-1);
            }); 

        };
        // until the length is reached and then I want it to delete the last one
        var lengthID = $scope.imgs.length; 
        var lengthLink = fireRef + "/" + lengthID;
        var lengthRef = new Firebase(lengthLink);
        lengthRef.remove();
    }
};

下次我肯定会使用服务/对象样式,但对于这个应用程序,这非常有用。无论如何解决它很有趣:)感谢所有帮助@Kato和@ m.e.conroy

2 个答案:

答案 0 :(得分:1)

您需要为ng-click创建一个方法,从$index传递ng-repeat,然后在ng-click调用的控制器方法中删除数组中的图像当用户确认后,然后将其从数据库中删除。从数组中删除它将自动触发ng-repeat重新渲染。

目前您正在使用jQuery从DOM中删除对象,但它仍然存在于Angular数组中。 Angular并不知道您使用jQuery从视图中删除对象。如果您执行上述操作,您甚至不需要使用jQuery或操作DOM,Angular将为您执行此操作。你也不必做$location.reload

$scope.deleteImg = function(i,id){
    if(confirm('..') === true){
        $scope.imgs.splice(i,1);
        // do firebase deletion
    }
};

在模板中:

<button type="button" class="delete" ng-click="deleteImg($index,img.id)">
    ...
</button>

修改

实际上,您只需要将$index参数传递给方法,因为splice会返回已删除的元素,而这将是您的图像对象。即:

$scope.deleteImg = function(i){
    var _img = $scope.imgs.splice(i,1);
    // use _img.id with your firebase delete statement
};

然后模板只是:

<button type="button" class="delete" ng-click="deleteImg($index)">...

答案 1 :(得分:0)

不确定什么是Firebase,但据我了解你删除了数组中的项目,它变为null。你需要.splice()$ scope.imgs数组才能真正从ng Repeat中删除一个项目