Question

Updates at the bottom I wrote a filter to manage what I displace in my ng-repeat. However, when the data being returned should be an empty array, in IE 9+ I get a crash, but in FF and Chrome it works fine.

BuildFilter below is called from angular.module('app').filter(filterId, buildFilter);

function buildFilter() {
    return function (input, limitTo, keyWords) {


        var outputPre = [];
        var outputPost = [];

        var d = new Date();
        console.log('filter event: '
            + d.getHours() + ":"
            + d.getMinutes() + ":"
            + d.getSeconds());

        var outputPre = [];
        if (!(limitTo === null
            || limitTo === undefined
            || limitTo === '')) {
            for (var i = 0; i < input.length; i++) {
                if (input[i] !== null && input[i] !== undefined) {
                    switch (limitTo) {
                        case 'edi':
                            if (input[i].dateReleased === null) {
                                outputPre.push(input[i]);
                            }
                            break;
                        case 'rel':
                            if (input[i].dateReleased !== null
                                && input[i].dateRetired === null) {
                                outputPre.push(input[i]);
                            }
                            break;
                        case 'ret':
                            if (input[i].dateRetired !== null) {
                                outputPre.push(input[i]);
                            }
                            break;
                        default:
                            outputPre.push(input[i]);
                    }
                }
            }
        }
        else {
            for (var i = 0; i < input.length; i++) {
                outputPre.push(input[i]);
            }
        }

        //Sanity Check Log Entry
        console.log('pre count: ' + outputPre.length);

        if (!(keyWords === null
            || keyWords === undefined
            || keyWords === '')) {
            var tkw = keyWords.toLocaleLowerCase();

            for (var i = 0; i < outputPre.length; i++) {

                var tn = outputPre[i].name.toLocaleLowerCase();

                if (tn.indexOf(tkw) > -1) {
                    outputPost.push(outputPre[i]);
                }
            }
        }
        else {
            for (var i = 0; i < outputPre.length; i++) {
                outputPost.push(outputPre[i]);
            }
        }

        //Sanity Check Log Entry
        console.log('post count: ' + outputPost.length);

        return outputPost;
    };
};

My sample data is:

var data= [ //for input
    {
        id: 0,
        dateCreated: '1/1/2014',
        dateReleased: null,
        dateRetired: null,
        name: 'Sample Data',
   },
   {
        id: 1,
        dateCreated: '1/1/2014',
        dateReleased: null,
        dateRetired: null,
        name: 'Other Sample Data',
    },
]

limitTo supports the following values: 'edi' 'rel', 'ret'

keyWords is just any string. It just looks to see if any part of the string is in the name field.

Update to post: Reduced the code to the following.

function isEdi(obj) {
    if ((obj.dateReleased === null)
        && (obj.dateRetired === null)) {
        return true;
    }
    return false;
}

function isRel(obj) {
    if ((obj.dateReleased !== null)
        && (obj.dateRetired === null)) {
        return true;
    }
    return false;
}

function isRet(obj) {
    if ((obj.dateReleased !== null)
        && (obj.dateRetired !== null)) {
        return true;
    }
    return false;
}

function buildFilter() {
    return function (input, limitTo) {

        var output = [];

        switch (limitTo) {
            case 'edi':
                output = input.filter(isEdi);
                break;
            case 'rel':
                output = input.filter(isRel);
                break;
            case 'ret':
                output = input.filter(isRet);
                break;
            default:
                output = input;
        }

        return output;
    };
};

IE crashes when the return is [], but works fine if the return as at least 1 record.

2ns Update to post:

Changed the repeat to ng-repeat="obj in objlist | filter:getObJFilter(objFilter) | orderBy:['+dateRetired','+dateReleased','+name']">

objFilter is a parameter to get the filter function to pass to filter. This way I am just extending the native filter rather than creating a new filter.

So my controller contains the following.

$scope.getFilter = function (val) {
    switch (val) {
        case 'edi':
            return isEdi();
            break;
        case 'rel':
            return isRel();
            break;
        case 'ret':
            return isRet();
            break;
        default:
            return function (obj) {return true };
   }
}

function isEdi() {
    return function(obj){
        if ((obj.dateReleased === null)
            && (obj.dateRetired === null)) {
            return true;
        }
        return false;
    }}

function isRel() {
    return function (obj) {
        if ((obj.dateReleased !== null)
            && (obj.dateRetired === null)) {
            return true;
        }
        return false;
    }
}

function isRet() {
    return function (obj) {
        if ((obj.dateReleased !== null)
            && (obj.dateRetired !== null)) {
            return true;
        }
        return false;
    }
}

I believe that I have done everything I can to eliminate the filter as being the problem. So I am now to where I believe there is a problem with an empty set being rendered in IE.

I will post a full test example in Plunkr tonight.

Note: I am also using AngularUI and Angular for UI Bootstrap. Shortcut for getting needed directives. However, I have had problems with UI Bootstrap on other issues, so I am going to replace a few more of their components to isolate the problem some more.

3rd Update I have removed all 3rd party directives. I did have UI Bootstrap to support TBS, so I eliminated that to save my sanity.

Was it helpful?

Solution 2

This isn't a problem with Angular.js, but with the UI.Bootstrap directives. Since I couldn't replicate the issue in Plunker, I started to look at the other directives. Eliminated the tab control out of the SPA, and replaced it with my own custom tabs based on TBS. Problem went away.

Further investigation reveals that this may be caused by a recursion problem in the UI.Bootstrap tab. So I will document my findings, and post to that GitHub.

I wouldn't have found this without the simple suggestion of posting code to Plunker, so I am the angular crew again.

My UI looked like:

<tabset>
    <tab header="some header">
        <div ng-repeat="...">
            ...

So the tabset and tab directive were getting fired at every change in my filter on the repeat. So I have removed the tabset and tab, and just replaced them with the standard TBS tabs.

OTHER TIPS

Put

<html xmlns:ng="http://angularjs.org">

or

 <html xmlns:ng="http://angularjs.org" id="ng-app" ng-app="optionalModuleName">

Follow this

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top