简体   繁体   English

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

[英]How to filter out or get rid of null objects within array? AngularJS, Firebase

My app is built using AngularJS, Yeoman stack, connected to the Firebase, AngularFire database. 我的应用程序是使用AngularJS Yeoman堆栈构建的,并连接到Firebase AngularFire数据库。 In my app I am trying to upload and delete pictures as shown below 在我的应用中,我尝试上传和删除图片,如下所示

在此处输入图片说明

It works fine except when I delete any imgs in between other images it does not actually remove the img but replaces it with an img with width and height of 0 as such... or it seems (more info in the bottom) 它工作正常,除非当我删除其他图像之间的任何img时,它实际上并没有删除img,而是以宽度和高度为0的img替换了它,或者...(底部显示更多信息)

在此处输入图片说明

and if I delete another "in-bewteen" img same deal 如果我删除另一个“ bewteen” img同样的交易

在此处输入图片说明

only when I delete the outer most img does the page really remove the imgs. 只有当我删除最外面的img时,页面才会真正删除img。

在此处输入图片说明

^^Notice how the one in between two other images on the top row did not delete because it is surrounded horizontally via other img objects. ^^注意,第一行中其他两个图像之间的图像如何被删除,因为它被其他img对象水平包围。 I had to firebase.remove the bottom two imgs to the right of the one I deleted very first and only then the whole bottom row was removed. 我必须firebase.remove删除我首先删除的那首右边的底部两张img,然后才删除整个底行。

I am not sure why I am getting this bug, could anyone give me some feedback? 我不确定为什么会收到此错误,有人可以给我一些反馈吗?

Here is my deleteImg and updateImg function in my controller 这是我的控制器中的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();
    }
};
}]);

Here is how I instantiate my array and Firebase database as well as create new $scope.selectedImg. 这是实例化数组和Firebase数据库以及创建新的$ scope.selectedImg的方法。 I am currently grabbing the data from firebase database and instantiating an array of Img objects. 我目前正在从Firebase数据库中获取数据,并实例化Img对象数组。 I use the array as my img models in the app. 我将数组用作应用程序中的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;
};

Here is my html view 这是我的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>

Using the chrome AngularJS extension I identified that the elements that I deleted within the database using the firebase remove() function, my $scope.imgs array still has a "null" element within the space in which I removed it. 通过使用chrome AngularJS扩展,我确定了使用firebase remove()函数在数据库中删除的元素,我的$ scope.imgs数组在我删除它的空间内仍然有一个“空”元素。 See below picture 见下图

在此处输入图片说明

How do I get past this bug? 我如何克服这个错误?


EDIT1: I followed @meconroy's advice and added the splice functionality and thought it worked perfectly, especially because I removed the location.reload() and in the view it showed that the pictures were getting deleted without a refresh. EDIT1:我遵循@meconroy的建议,并添加了拼接功能,并认为它可以正常工作,特别是因为我删除了location.reload()并在视图中显示图片已删除而没有刷新。 However, when I do refresh the page the same "ghost" imgs and its delete buttons are showing up again. 但是,当我刷新页面时,相同的“ ghost” img及其删除按钮再次出现。

When I checked the AngularJS chrome extension for the scope models, it was showing that the outermost img (the img that is to the right of the "in-between" ghost imgs) is taking over the deleted images, meaning the deleted images are getting set with the same name, id, and other attributes of the outer most img object. 当我检查范围模型的AngularJS chrome扩展时,它表明最外面的img(“中间” ghost img右侧的img)将接管已删除的图像,这意味着已删除的图像正在获取使用最外面的img对象的相同名称,id和其他属性进行设置。 Once again, according to the chrome extension the array elements are not removed but only replaced. 再一次,根据chrome扩展名,数组元素不会被删除,而只会被替换。 Once I refresh though it goes back to the same issue I had before of "null" element in array. 刷新后,尽管回到了我之前遇到的数组“ null”元素相同的问题。 This is weird because in my Firebase dashboard it shows that the imgs are indeed deleted however it does not reflect on my view until the outer most img is deleted. 这很奇怪,因为在我的Firebase仪表板中它显示确实删除了img,但是直到最外面的img被删除,它才反映在我的视图上。 Below is a view of my Firebase dashboard and index. 以下是我的Firebase仪表板和索引的视图。 Only when the img 24 is deleted does the changes actually apply. 仅当img 24被删除时,更改才真正生效。

在此处输入图片说明


EDIT2: As referenced by @katowulf in this article ( https://www.firebase.com/blog/2014-04-28-best-practices-arrays-in-firebase.html ), I am having the exact problem he describes in the "Good Use Cases for Storing Data in Arrays" section. EDIT2:正如@katowulf在本文( https://www.firebase.com/blog/2014-04-28-best-practices-arrays-in-firebase.html )中所引用的那样,我遇到了他所描述的确切问题在“在阵列中存储数据的好用例”部分中。 Currently, I am trying to target each and every one of the imgs after the one that I delete and change their IDs to id - 1 as well as the imgs location in the fire ref to firebar_url/ref - 1 but I feel like I am trying to force an implementation rather than finding the correct solution. 目前,我正在尝试针对我删除的所有img并将其ID更改为id - 1以及将Fire ref中的imgs位置更改为firebar_url/ref - 1但是我感觉自己试图强制实施而不是找到正确的解决方案。 Should I try to refactor my code to utilize objects like he suggests? 我是否应该尝试重构代码以利用他建议的对象? (I tried that initially but I wasn't able to grab the objects and its attributes therefore had to rely on firebase snapshots to instantiate and create my array. Reference: How would I convert my new Object data I am retrieving from Firebase into the JSON form as I had before ). (起初我尝试过,但是我无法抓取对象,因此它的属性必须依靠Firebase快照来实例化并创建数组。参考: 如何将我从Firebase检索到的新Object数据转换为JSON形式与我以前一样 )。 Any feedback is welcome. 欢迎任何反馈。


MY SOLUTION: To manually change index values as well as corresponding 'id' attributes to -1 for all img objects following the one that has been deleted. 我的解决方案:要为已删除的img对象之后的所有img对象手动将索引值以及相应的'id'属性更改为-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();
    }
};

Next time I will most definitely use services/object style but for this app this works great. 下次,我一定会使用服务/对象样式,但是对于此应用程序,它的效果很好。 It was fun to solve it anyway :) Thanks for all the help @Kato and @meconroy 无论如何,解决它很有趣:)感谢@Kato和@meconroy的所有帮助

You need to create a method for ng-click that passes the $index from the ng-repeat then in your controller method called by ng-click remove the image from the array (of course after the user confirms) and remove it from the database. 您需要为ng-click创建一个从ng-repeat传递$index的方法,然后在ng-click调用的控制器方法中,从数组中删除图像(当然,在用户确认后),然后从数据库中删除它。 removing it from the array will automatically trigger ng-repeat to re-render. 从阵列中删除它会自动触发ng-repeat重新渲染。

Currently you're using jQuery to remove the object from the DOM but it still exists in the Angular array. 当前,您正在使用jQuery从DOM中删除对象,但它仍然存在于Angular数组中。 Angular doesn't know you used jQuery to remove the object from the view. Angular不知道您使用jQuery从视图中删除了对象。 If you do what is describe above you won't even need to use jQuery or manipulate the DOM, Angular will do it for you. 如果您执行上述操作,您甚至不需要使用jQuery或操作DOM,Angular会为您完成。 You should not have to do a $location.reload either. 您也不必执行$location.reload

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

In template: 在模板中:

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

EDIT 编辑

Actually you'll only need to pass the $index parameter to the method since splice returns the removed element and that will be your image object. 实际上,您只需要将$index参数传递给该方法,因为splice返回移除的元素,这将成为您的图像对象。 ie: 即:

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

and then the template is simply just: 然后模板就是:

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

Not sure what is Firebase, but as i understan you delete item in array, that become null. 不知道什么是Firebase,但是由于我要删除数组中的项,因此该项变为null。 And you need to .splice() $scope.imgs array to really remove an item from ngRepeat 并且您需要.splice()$ scope.imgs数组才能真正从ngRepeat中删除项目

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM