Verificando se o objeto está vazio, funciona com o ng-show, mas não do controlador?

99

Eu tenho um objeto JS declarado assim

$scope.items = {};

Eu também tenho uma solicitação $ http que preenche este objeto com itens. Gostaria de detectar se este item está vazio, parece que o ng-show suporta isso ... Eu entro

ng-show="items"

e magicamente funciona, eu também gostaria de fazer o mesmo em um controlador, mas não consigo fazê-lo funcionar, parece que posso ter que iterar sobre o objeto para ver se ele tem alguma propriedade ou usar lodash ou sublinhado .

Existe uma alternativa?

Eu tentei

alert($scope.items == true);

mas sempre retorna falso, quando o objeto é criado e quando preenchido com $http, então não está funcionando dessa forma.

Martin
fonte
1
Em um controlador, você está apenas usando javascript, então as respostas a esta pergunta se aplicam: stackoverflow.com/questions/4994201/is-object-empty
Cyrille Ka

Respostas:

62

Usar um literal de objeto vazio não é necessário aqui, você pode usar nulo ou indefinido:

$scope.items = null;

Desta forma, ng-showdeve continuar funcionando, e em seu controlador você pode apenas fazer:

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

E em seus $httpretornos de chamada, você faz o seguinte:

$http.get(..., function(data) {
    $scope.items = {
        data: data,
        // other stuff
    };
});
Ye Liu
fonte
Olá, obrigado pela resposta, mas preciso definir as propriedades do objeto antes de realmente receber informações de $ http. se for nulo, então não posso fazer items.available = true, posso? Tive a impressão de que deveria criar um objeto
Martin
Se eu tiver um item = {}; não há como confirmar isso de um controlador? claro que não seria nulo aqui.
Martin
1
Este requisito não está em sua pergunta, então minha resposta é baseada no cenário simplificado. Se você realmente precisa de um objeto para começar, pode tentar $scope.items = {available: false}, e ng-show="items.available", e em seu controlador apenas verifique if (items.available) {...}.
Ye Liu
obrigado! Na verdade, acabei testando com undefined e funcionou muito bem. obrigado.
Martin
@YeLiu se você quiser tornar um item nulo em itens, você não terá permissão para fazer isso duas vezes, o angular lançará uma exceção que informa que não permite ingênuos dentro de uma coleção por razões desconhecidas para mim até agora.
Burimi
199

Ou você pode mantê-lo simples fazendo algo assim:

alert(angular.equals({}, $scope.items));
teste123
fonte
Meu também. Graças a Deus, não precisei sobrecarregar mais funções para testá-lo.
Jimmy Kane
1
Apenas uma nota, para o meu teste (Chrome 45), a igualdade de javascript simples também funcionou:({} === $scope.items)
Jesper Rønn-Jensen
hmm, isso avalia como falso, o que dá? ({} == {})
chrismarx
Abordagem muito inteligente! One liners são sempre melhores :)
supersan
se usado na visualização e use o modelo de visualização como escopo, certifique-se de adicionar angular ao modelo de visualização, ou seja, vm.angular.equals ({}, itens)
cinek
71

Em um projeto privado, escrevi este filtro

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

uso:

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

testando:

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

});

Saudações.

jcamelis
fonte
2
Funciona como um encanto. Obrigado por compartilhar!
Chnoch
2
Acredito que os filtros devem analisar o conteúdo e retornar um subconjunto do conteúdo. O que você descreve parece mais uma função colocada no escopo do que um filtro. Consulte docs.angularjs.org/api/ng/filter/filter para obter mais informações.
kmkm de
4
Acho que você está falando sobre um filtro específico chamado filter ou 'filterFilter'. Um filtro em angular pode retornar qualquer coisa que você quiser, não apenas um subconjunto da entrada fornecida. Consulte docs.angularjs.org/api/ng/filter .
jcamelis
61

outra linha simples:

var ob = {};
Object.keys(ob).length // 0
Jaf0
fonte
2
Isso é elegante, mas você deve verificar a compatibilidade do ECMAScript5 nos navegadores que deseja. A maior armadilha é que isso não funcionará no IE8.
jmgem
8
Como um detalhe técnico, angula não suporta oficialmente o IE8 no branch 1.3 (dev), nem executa testes para ele em docs.angularjs.org/guide/ie 1.2 (estável) ... Além disso, quanto menos damos suporte ao IE8, talvez finalmente desapareça. <inserir refutação corporativa>
jaf0
2
A melhor resposta se você realmente precisa lidar com um objeto vazio
chovy
27

Se você não pudesse ter os itens OBJ iguais a nulos, você pode fazer isso:

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

e na visualização você pode fazer:

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

Você pode fazer

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

Somente se o seu navegador suportar ECMAScript 5. Por exemplo, o IE 8 não oferece suporte a esse recurso.

Veja http://kangax.github.io/compat-table/es5/ para mais informações

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

uma versão mais limpa disso pode ser:

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

onde o resultado será indefinido se nenhuma propriedade do objeto for definida.

n0mad
fonte
6

Ou, se estiver usando lo-traço: _.empty (valor).

"Verifica se o valor está vazio. Objetos de vetores, strings ou argumentos com comprimento 0 e objetos sem propriedades enumeráveis ​​próprias são considerados" vazios "."

Jeff Pace
fonte
-2

Verificar objeto vazio

$scope.isValid = function(value) {
    return !value
}
Taran
fonte
isso é simplesmente errado. Objetos vazios não podem ser testados assim
Kaiser
-11

você pode verificar o comprimento dos itens

ng-show="items.length"
Pradip Chongbang
fonte
1
Não entendo por que essa resposta tem -1 voto? Alguém pode me explicar isso, por favor?
iluu
14
@KarolinaKafel porque itemsé um objeto e os objetos não têm .lengthpropriedade (normalmente) - os arrays os têm
llamerr
2
Não é um cara de array :)
Ghazanfar Khan
@KarolinaKafel não é uma matriz, então items.length é sempre indefinido.
Fabricio
Ya ya aquele humano se enganou, -1 também teria mostrado que esta resposta está errada, por que -10? as pessoas crescem :)
Aadam