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.


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

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

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.


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

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


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.


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 "."


-2

Verificar objeto vazio

$scope.isValid = function(value) {
    return !value
}

isso é simplesmente errado. Objetos vazios não podem ser testados assim
Kaiser

-11

você pode verificar o comprimento dos itens

ng-show="items.length"

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.