99

I have a JS object declared like so

$scope.items = {};

I also have a $http request that fills this object with items. I would like to detect if this item is empty, it appears that ng-show supports this... I enter

ng-show="items"

and magically it works,I would also like to do the same from a controller but i can't seem to get it to work, it appears I may have to iterate over the object to see if it has any properties or use lodash or underscore.

Is there an alternative?

I did try

alert($scope.items == true);

but it always returns false , when the object is created and when populated with $http, so its not working that way.

Rahil Wazir
  • 10,007
  • 11
  • 42
  • 64
Martin
  • 23,844
  • 55
  • 201
  • 327
  • 1
    In a controller, you are just using javascript, so answers of this question would apply: http://stackoverflow.com/questions/4994201/is-object-empty – Cyrille Ka Jul 24 '13 at 16:10

9 Answers9

199

Or you could keep it simple by doing something like this:

alert(angular.equals({}, $scope.items));
testing123
  • 11,367
  • 10
  • 47
  • 61
71

In a private project a wrote this filter

angular.module('myApp')
    .filter('isEmpty', function () {
        var bar;
        return function (obj) {
            for (bar in obj) {
                if (obj.hasOwnProperty(bar)) {
                    return false;
                }
            }
            return true;
        };
    });

usage:

<p ng-hide="items | isEmpty">Some Content</p>

testing:

describe('Filter: isEmpty', function () {

    // load the filter's module
    beforeEach(module('myApp'));

    // initialize a new instance of the filter before each test
    var isEmpty;
    beforeEach(inject(function ($filter) {
        isEmpty = $filter('isEmpty');
    }));

    it('should return the input prefixed with "isEmpty filter:"', function () {
          expect(isEmpty({})).toBe(true);
          expect(isEmpty({foo: "bar"})).toBe(false);
    });

});

regards.

jcamelis
  • 1,289
  • 1
  • 9
  • 10
  • 2
    I believe filters should parse content and return a subset of the content. What you describe seems more like a function placed on the scope than a filter. See https://docs.angularjs.org/api/ng/filter/filter for more information. – kmkm Oct 01 '14 at 13:30
  • 4
    I think that you are talking about a particular filter called filter or 'filterFilter'. A filter in angular can return anything you want, not just a subset of the given input. See https://docs.angularjs.org/api/ng/filter/ . – jcamelis Oct 31 '14 at 12:19
63

Use an empty object literal isn't necessary here, you can use null or undefined:

$scope.items = null;

In this way, ng-show should keep working, and in your controller you can just do:

if ($scope.items) {
    // items have value
} else {
    // items is still null
}

And in your $http callbacks, you do the following:

$http.get(..., function(data) {
    $scope.items = {
        data: data,
        // other stuff
    };
});
Ye Liu
  • 8,946
  • 1
  • 38
  • 34
  • Hi thanks for the reply, but I need to set properties on the object before I have actually received info from $http. if its null then I couldn't do items.available = true could I ? I was under the impression that i had to create an object – Martin Jul 24 '13 at 16:27
  • If i do have a items = {}; is there not anyway to confirm this from a controller ? of course it wouldn't be null here. – Martin Jul 24 '13 at 16:29
  • 1
    This requirement isn't in your question, so my answer is based on the over simplified scenario. If you really need an object to start with, you can try `$scope.items = {available: false}`, and `ng-show="items.available"`, and in your controller just check `if (items.available) {...}`. – Ye Liu Jul 24 '13 at 16:39
  • thanks! actually i ended up testing it with undefined and it worked great. thanks. – Martin Jul 27 '13 at 13:09
  • @YeLiu if you want to make an item in items null, you wont be allowed to make that twice, angular will throw an exception which tells you it does not allow dupes within a collection for unknown reasons for me so far. – Rosmarine Popcorn Jun 23 '15 at 18:24
61

another simple one-liner:

var ob = {};
Object.keys(ob).length // 0
jaf0
  • 1,148
  • 10
  • 20
  • 2
    This is elegant, but you have to check for ECMAScript5 compatibility in the browsers you're targeting. The major pitfall is that this won't work in IE8. – jmgem Oct 27 '14 at 01:40
  • 8
    As a technicality, angula does not officially support IE8 in the 1.3 (dev) branch, nor do they run tests for it on 1.2 (stable) https://docs.angularjs.org/guide/ie... Furthermore, the less we support IE8, maybe it will finally disappear. – jaf0 Oct 27 '14 at 15:00
  • 2
    Best answer if you really must deal with an empty object – chovy Jul 19 '15 at 06:41
27

If you couldn't have the items OBJ equal to null, you can do this:

$scope.isEmpty = function (obj) {
    for (var i in obj) if (obj.hasOwnProperty(i)) return false;
    return true;
};

and in the view you can do:

<div ng-show="isEmpty(items)"></div>

You can do

var ob = {};
Object.keys(ob).length

Only if your browser supports ECMAScript 5. For Example, IE 8 doesn't support this feature.

See http://kangax.github.io/compat-table/es5/ for more infos

mattia.corci
  • 554
  • 6
  • 11
7
if( obj[0] )

a cleaner version of this might be:

if( typeof Object.keys(obj)[0] === 'undefined' )

where the result will be undefined if no object property is set.

n0mad
  • 320
  • 4
  • 5
6

Or, if using lo-dash: _.empty(value).

"Checks if value is empty. Arrays, strings, or arguments objects with a length of 0 and objects with no own enumerable properties are considered "empty"."

Jeff Pace
  • 79
  • 1
  • 3
-2

Check Empty object

$scope.isValid = function(value) {
    return !value
}
Taran
  • 2,895
  • 25
  • 22
-11

you can check length of items

ng-show="items.length"
Jose Ricardo Bustos M.
  • 8,016
  • 6
  • 40
  • 62
Pradip Chongbang
  • 2,188
  • 1
  • 11
  • 6