Prüfen, ob das Objekt leer ist, funktioniert mit ng-show, aber nicht vom Controller?

99

Ich habe ein JS-Objekt so deklariert

$scope.items = {};

Ich habe auch eine $ http-Anfrage, die dieses Objekt mit Elementen füllt. Ich möchte feststellen, ob dieses Element leer ist. Es scheint, dass ng-show dies unterstützt ... Ich gebe ein

ng-show="items"

und magisch funktioniert es, ich würde das auch gerne von einem Controller aus tun, aber ich kann es scheinbar nicht zum Laufen bringen. Es scheint, dass ich über das Objekt iterieren muss, um zu sehen, ob es irgendwelche Eigenschaften hat oder lodash oder Unterstrich verwendet .

Gibt es eine Alternative?

Ich habe es versucht

alert($scope.items == true);

Es wird jedoch immer false zurückgegeben, wenn das Objekt erstellt und mit gefüllt wird $http, sodass es nicht so funktioniert.

Martin
quelle
1
In einem Controller verwenden Sie nur Javascript, daher gelten die Antworten auf diese Frage: stackoverflow.com/questions/4994201/is-object-empty
Cyrille Ka

Antworten:

62

Die Verwendung eines leeren Objektliteral ist hier nicht erforderlich. Sie können null oder undefiniert verwenden:

$scope.items = null;

Auf diese Weise ng-showsollte weiter funktionieren, und in Ihrem Controller können Sie einfach tun:

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

Und in Ihren $httpRückrufen tun Sie Folgendes:

$http.get(..., function(data) {
    $scope.items = {
        data: data,
        // other stuff
    };
});
Ye Liu
quelle
Hallo, danke für die Antwort, aber ich muss Eigenschaften für das Objekt festlegen, bevor ich tatsächlich Informationen von $ http erhalten habe. Wenn es null ist, kann ich keine Elemente ausführen. verfügbar = wahr, oder? Ich hatte den Eindruck, dass ich ein Objekt erstellen musste
Martin
Wenn ich einen Artikel habe = {}; Gibt es nicht sowieso eine Bestätigung von einem Controller? Natürlich wäre es hier nicht null.
Martin
1
Diese Anforderung ist in Ihrer Frage nicht enthalten, daher basiert meine Antwort auf dem stark vereinfachten Szenario. Wenn Sie wirklich ein Objekt benötigen , mit zu beginnen, können Sie versuchen $scope.items = {available: false}, und ng-show="items.available", und in dem Controller einfach zu überprüfen if (items.available) {...}.
Ye Liu
Vielen Dank! Eigentlich habe ich es mit undefined getestet und es hat super funktioniert. Vielen Dank.
Martin
@YeLiu Wenn Sie ein Element in Elementen auf null setzen möchten, dürfen Sie dies nicht zweimal festlegen. Angular löst eine Ausnahme aus, die besagt, dass Dupes innerhalb einer Sammlung aus unbekannten Gründen für mich bisher nicht zulässig sind.
Burimi
199

Oder Sie könnten es einfach halten, indem Sie so etwas tun:

alert(angular.equals({}, $scope.items));
Testen123
quelle
Meins auch. Gott sei Dank musste ich nicht mehr Funktionen überladen, um es zu testen.
Jimmy Kane
1
Nur eine Anmerkung, für meinen Test (Chrom 45) hat auch die einfache Javascript-Gleichheit funktioniert:({} === $scope.items)
Jesper Rønn-Jensen
hmm, das ergibt falsch, was gibt es? ({} == {})
Chrismarx
Sehr kluger Ansatz! Ein Liner ist immer besser :)
Supersan
Ich danke dir sehr! :)
Francis Rodrigues
71

In einem privaten Projekt hat a diesen Filter geschrieben

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

Verwendung:

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

testen:

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);
    });

});

Grüße.

jcamelis
quelle
2
Klappt wunderbar. Danke für das Teilen!
Chnoch
2
Ich glaube, Filter sollten Inhalte analysieren und eine Teilmenge des Inhalts zurückgeben. Was Sie beschreiben, scheint eher eine Funktion zu sein, die auf dem Bereich platziert ist, als ein Filter. Weitere Informationen finden Sie unter docs.angularjs.org/api/ng/filter/filter .
kmkm
4
Ich denke, Sie sprechen von einem bestimmten Filter namens filter oder 'filterFilter'. Ein Filter im Winkel kann alles zurückgeben, was Sie wollen, nicht nur eine Teilmenge der angegebenen Eingabe. Siehe docs.angularjs.org/api/ng/filter .
JCamelis
61

ein weiterer einfacher Einzeiler:

var ob = {};
Object.keys(ob).length // 0
jaf0
quelle
2
Dies ist elegant, aber Sie müssen die ECMAScript5-Kompatibilität in den Browsern überprüfen, auf die Sie abzielen. Die größte Gefahr besteht darin, dass dies in IE8 nicht funktioniert.
jmgem
8
Aus technischen Gründen unterstützt Angula IE8 im 1.3 (dev) -Zweig weder offiziell noch führt es Tests für 1.2 (stabile) docs.angularjs.org/guide/ie durch ... Je weniger wir IE8 unterstützen, vielleicht wird es endlich verschwinden. <Corporate Widerlegung einfügen>
jaf0
2
Beste Antwort, wenn Sie wirklich mit einem leeren Objekt umgehen müssen
chovy
27

Wenn Sie die Elemente OBJ nicht gleich null haben konnten, können Sie Folgendes tun:

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

und in der Ansicht können Sie tun:

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

Du kannst tun

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

Nur wenn Ihr Browser ECMAScript 5 unterstützt. Beispielsweise unterstützt IE 8 diese Funktion nicht.

Siehe http://kangax.github.io/compat-table/es5/ für mehr Infos

mattia.corci
quelle
7
if( obj[0] )

Eine sauberere Version davon könnte sein:

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

Dabei ist das Ergebnis undefiniert, wenn keine Objekteigenschaft festgelegt ist.

n0mad
quelle
6

Oder wenn Sie lo-dash verwenden: _.empty (Wert).

"Überprüft, ob der Wert leer ist. Arrays, Zeichenfolgen oder Argumente Objekte mit einer Länge von 0 und Objekte ohne eigene aufzählbare Eigenschaften werden als" leer "betrachtet."

Jeff Pace
quelle
-2

Überprüfen Sie das leere Objekt

$scope.isValid = function(value) {
    return !value
}
Taran
quelle
Das ist einfach falsch. Leere Objekte können nicht so getestet werden
Kaiser
-11

Sie können die Länge der Elemente überprüfen

ng-show="items.length"
Pradip Chongbang
quelle
1
Ich verstehe nicht, warum diese Antwort -1 Stimmen hat? Kann mir das bitte jemand erklären?
iluu
14
@ KarolinaKafel, weil itemses ein Objekt ist und Objekte .length(normalerweise) keine Eigenschaft haben - Arrays haben sie
llamerr
2
Es ist kein Array-Typ :)
Ghazanfar Khan
@KarolinaKafel ist kein Array, dann ist items.length immer undefiniert.
Fabricio
Ya ya dieser Mensch hat sich geirrt, -1 hätte auch gezeigt, dass diese Antwort falsch ist, warum -10? Leute werden erwachsen :)
Aadam