简体   繁体   中英

Filtering an array of nested objects

I am trying to make a filter pipe in Angular2 which is going to have to filter through an array containing multiple nested objects. These objects are coming from Salesforce and sometimes will contain nested objects like the following example:

Object {
    Id: "a0436000001awB5AAI",
    Name: "Some product",
    Store__c: "a0436000001awC2JJU",
    Product__c: "a0136000001UGzzAAG",
    Product__r: Object {
        Id: "a0136000001UGzzAAG",
        Name: "Parent product",
        ...
    },
    ...
}

Normal sorting methods don't work very well because they don't tend to go multiple levels. I have been trying to write my own, but I can't seem to figure it out. Here is what I have right now:

// # Filter Array of Objects
@Pipe({ name: 'filter' })
export class FilterArrayPipe implements PipeTransform {

    transform(value, args) {

        let filterKeys: string[];
        if (args[1]) {
            let parts = args[1].replace(' ', '').split(',');
            filterKeys = parts;
        }

        if (!args[0]) {

            return value;

        } else if (value) {

            return value.filter(item => {

                for (let key in item) {

                    if ((typeof item[key] === 'string' || item[key] instanceof String && item[key]) && (item[key].indexOf(args[0]) !== -1)) {

                        if (filterKeys && filterKeys.length > 0) {

                            if (item[key] in filterKeys) {

                                return true;

                            }
                        }
                        else {

                            return true;

                        }
                    }

                }
            });
        }
    }

}

It doesn't really work at all right now.

All you need to make your code work is to change the line:

if (item[key] in filterKeys) {

The 'in operator' is used for checking if a property exists on an object.

Instead, for arrays you use:

if (filterKeys.indexOf(key) > -1) {

Here is a working plunker

I figured it out. It's not perfect, but it does the job:

private flattenObject(ob) {
        var toReturn = {};

        for (var i in ob) {
            if (!ob.hasOwnProperty(i)) continue;

            if ((typeof ob[i]) == 'object') {
                var flatObject = this.flattenObject(ob[i]);
                for (var x in flatObject) {
                    if (!flatObject.hasOwnProperty(x)) continue;

                    toReturn[i + '.' + x] = flatObject[x];
                }
            } else {
                toReturn[i] = ob[i];
            }
        }
        return toReturn;
    };

    transform(value, args) {

        let filterKeys: string[];
        if (args[1]) {
            console.log(args[1]);
            if (typeof args[1] === 'string') {
                console.log('string');
                let parts = args[1].replace(' ', '').split(',');
                filterKeys = parts;
            } else if (typeof args[1] === 'object') {
                console.log('object');
                filterKeys = args[1];
            }
        }


        if (!args[0]) {
            return value;
        } else if (value) {

            let retArr: Object[] = [];

            for (let obj of value) {

                let filterable: Object = this.flattenObject(obj);

                    for (let key in filterable) {

                        key = String(key);
                        let val = String(filterable[key]);

                        if (val.indexOf(args[0]) !== -1) {
                            if (filterKeys && filterKeys.length > 0) {
                                if (filterKeys.indexOf(key) > -1) {
                                    retArr.push(obj);
                                }
                            }
                            else {
                                return true;
                            }
                        }

                    }

            }

            return retArr;

        }
    }

Basically just flatten the Object and then filter over it.

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