简体   繁体   中英

Angular / lodash - remove multiple objects from a collection

SOLUTION TO MY ORIGINAL QUESTION

Thanks to the brilliance of Dan's answer below I've managed to reduce my original code significantly. I have dropped some of flexibility I originally had built ie use multi properties vs static prop, but an easy fix in a later version and a no-brainer in terms of code size :) Again, many thanks to Dan. In this example I've included 2 forget() methods wrapped in an Angular Collection factory.

Collection.$inject = ['Constructor', 'Article'];
function Collection(Constructor, Article) {

    var Model = Article,
        Collection = {},
        collection = [],
        add,
        forget;

    function Extendable(data, keys) {
        Constructor.call(this, data, Model.fillable);
    }

    Extendable.prototype = Object.create(Constructor.prototype);
    Extendable.prototype.constructor = Extendable;
    Collection = Extendable.prototype;
    collection = Collection.items = [];

    add = function(item) {
        if (item instanceof Model) {
            collection.push(item);
        }
    };
    Collection.add = add;

    // EXAMPLE OF SINGLE ID DELETE I.E. SIMPLE VERSION
    forget = function(id) {
        collection = _.dropWhile(collection, {id: id});
    };
    Collection.forget = forget;

    // OR!!! EXAMPLE OF MULTI ID VALUE || ARRAY
    forget = function(id) {
        var ids = [];
        if (_.isArray(id)) {
            ids = id;
        } else {
            ids.push(parseInt(id));
        }
        return _.dropWhile(collection, function (n) {
            return _.includes(ids, n.id);
        });
    };
    Collection.forget = forget;

    // remove rest of factory for brevity sake
    return Extendable;
};

DEV TOOLS

Angular 1.4.8, lodash 2.x

QUESTION:

I'm still an Angular & JS. Is there a more concise approach to deleting multiple object instances (eg Article/s in a Articles Collection). The forget() method accepts 1 argument that could a string||integer||array (of strings or integers)

EXAMPLE:

var articleIdsToRemove = [1, '2', 3];

OR

var articleIdsToRemove = 1; 

var articles = newCollection();

For brevity sake i've excluded the add method for adding Article instances to collection but lets assume we have 10, each with a prop of id

MY CURRENT APPROACH

  1. validate type of value as above ie array, str, int, and set all values to an array of ints ie ids
  2. then iterate through the array of ids to find an index for Article instance that has prop id and is equal to value id
  3. if found push the index onto indices. One we have all matching indexes then send it Array.prototype.remove to remove multiple items from the collection array. Once that is done then re-sort collection

removed Angular factory wrapper for brevity sake, but assume all of this is in a angular factory called Collection which injects an Article factory that is data model. In summary Collection (articles) contains many Article

    // We set a collections array inside of object to hold all Article instances
    collection = Extendable.prototype.items = [];
    // NOTE add articles method removed, but assume weve added multiple Article's to collection 

    forget = function(id) {
        var ids = [],
            index = null,
            indices = [];
        if (angular.isDefined(id) && !_.isEmpty(id)) {
            ids = _.isArray(id) ? id : isInt(id) ? [Number(id)] : [];
            if (ids.length) {
                _.each(ids, function(id) {
                    index = getIndex('app_id', id);
                    if (index) {
                        indices.push(index)
                    }
                });
                if (indices.length) {
                    collection = collection.remove(indices)
                }
            }
        }
    };
    Extendable.prototype.forget = forget;

    function isInt(n){
        return Number(n) === n && n % 1 === 0;
    }

    function getIndex(prop, value) {
        return _.indexOf(collection, function(d) {
            if (hasProp(d, prop)) {
                return d[prop] == value;
            }
        });
    }

    function hasProp (obj, prop) {
        return Object.prototype.hasOwnProperty.call(obj, prop);
    }

    Array.prototype.remove = function(){
        var args = Array.apply(null, arguments);
        var indices = [];
        for(var i = 0; i < args.length; i++){
            var arg = args[i];
            var index = this.indexOf(arg);
            while(index > -1){
                indices.push(index);
                index = this.indexOf(arg, index + 1);
            }
        }
        indices.sort();
        for(var i = 0; i < indices.length; i++){
            var index = indices[i] - i;
            this.splice(index, 1);
        }
    };

Take a look at this

var forget = function(id) {
  var ids = [];
  if (_.isArray(id)) {
    ids = id;
  } else {
    ids.push(parseInt(id));
  }
  return _.dropWhile(articles, function(n) {
    return _.includes(ids, n.id);
  });
}

Example here: http://jsfiddle.net/hFm7j/226/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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