0

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.

4
  • what do you want to achieve with this Pipe filter ? Commented Mar 20, 2016 at 7:42
  • Your code suggest that you are trying to filter like this: "*ngFor="#i of someArray | filter:'a0136000001UGzzAAG':'Id,Sotre__c' ". Am I right ? Also, you are using using the 'in' operator wrong. in the line 'if (item[key] in filterKeys)', you are using it with array while it should be used with object. Commented Mar 20, 2016 at 11:40
  • @Abdulrahman you're exactly right about how I'm trying to use the pipe. Commented Mar 20, 2016 at 14:45
  • @A_Singh I'm attaching the filter to an ngModel called queueD ilter and attempting to filter the records in a table Commented Mar 20, 2016 at 14:46

2 Answers 2

1

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

Sign up to request clarification or add additional context in comments.

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.