Verificando si el objeto está vacío, ¿funciona con ng-show pero no desde el controlador?

99

Tengo un objeto JS declarado así

$scope.items = {};

También tengo una solicitud $ http que llena este objeto con elementos. Me gustaría detectar si este elemento está vacío, parece que ng-show admite esto ...

ng-show="items"

y mágicamente funciona, también me gustaría hacer lo mismo desde un controlador, pero parece que no puedo hacer que funcione, parece que tengo que iterar sobre el objeto para ver si tiene alguna propiedad o usar lodash o subrayado .

¿Existe alguna alternativa?

lo intenté

alert($scope.items == true);

pero siempre devuelve falso, cuando se crea el objeto y cuando se llena con $http, por lo que no funciona de esa manera.

Martín
fuente
1
En un controlador, solo está usando javascript, por lo que las respuestas de esta pregunta se aplicarían: stackoverflow.com/questions/4994201/is-object-empty
Cyrille Ka

Respuestas:

62

El uso de un objeto literal vacío no es necesario aquí, puede usar nulo o indefinido:

$scope.items = null;

De esta manera, ng-showdebería seguir funcionando, y en su controlador solo puede hacer:

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

Y en sus $httpdevoluciones de llamada, hace lo siguiente:

$http.get(..., function(data) {
    $scope.items = {
        data: data,
        // other stuff
    };
});
Ye Liu
fuente
Hola, gracias por la respuesta, pero necesito establecer propiedades en el objeto antes de recibir información de $ http. si es nulo, entonces no podría hacer items. Available = true, ¿podría? Tenía la impresión de que tenía que crear un objeto
Martin
Si tengo items = {}; ¿No hay alguna forma de confirmar esto desde un controlador? por supuesto, aquí no sería nulo.
Martin
1
Este requisito no está en su pregunta, por lo que mi respuesta se basa en el escenario simplificado. Si realmente necesita un objeto para empezar, puede probar $scope.items = {available: false}, y ng-show="items.available", y en su controlador simplemente verifique if (items.available) {...}.
Ye Liu
¡Gracias! de hecho terminé probándolo con undefined y funcionó muy bien. Gracias.
Martin
@YeLiu si desea que un elemento en elementos sea nulo, no se le permitirá hacerlo dos veces, angular lanzará una excepción que le indica que no permite engaños dentro de una colección por razones desconocidas para mí hasta ahora.
Burimi
199

O puede hacerlo simple haciendo algo como esto:

alert(angular.equals({}, $scope.items));
probando 123
fuente
El mío también. Gracias a Dios, no tuve que sobrecargar más funciones para probarlo.
Jimmy Kane
1
Solo una nota, para mi prueba (Chrome 45), la igualdad de JavaScript simple también funcionó:({} === $scope.items)
Jesper Rønn-Jensen
hmm, esto se evalúa como falso, ¿qué ocurre? ({} == {})
chrismarx
¡Enfoque muy inteligente! Los one liners siempre son mejores :)
supersan
si se usa en la vista y usa el modelo de vista como alcance, asegúrese de agregar angular al modelo de vista, es decir, vm.angular.equals ({}, elementos)
cinek
71

En un proyecto privado a escribió 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>

pruebas:

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

});

Saludos.

jcamelis
fuente
2
Funciona de maravilla. ¡Gracias por compartir!
Chnoch
2
Creo que los filtros deberían analizar el contenido y devolver un subconjunto del contenido. Lo que describe parece más una función colocada en el alcance que un filtro. Consulte docs.angularjs.org/api/ng/filter/filter para obtener más información.
kmkm
4
Creo que estás hablando de un filtro en particular llamado filter o 'filterFilter'. Un filtro en angular puede devolver cualquier cosa que desee, no solo un subconjunto de la entrada dada. Consulte docs.angularjs.org/api/ng/filter .
jcamelis
61

otra simple frase:

var ob = {};
Object.keys(ob).length // 0
jaf0
fuente
2
Esto es elegante, pero debe verificar la compatibilidad de ECMAScript5 en los navegadores a los que se dirige. El mayor problema es que esto no funcionará en IE8.
jmgem
8
Como tecnicismo, angula no admite oficialmente IE8 en la rama 1.3 (dev), ni ejecutan pruebas para él en 1.2 (estable) docs.angularjs.org/guide/ie ... Además, cuanto menos admitimos IE8, tal vez finalmente desaparezca. <insertar refutación corporativa>
jaf0
2
La mejor respuesta si realmente debe lidiar con un objeto vacío
chovy
27

Si no puede tener los elementos OBJ igual a nulo, puede hacer esto:

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

y en la vista puedes hacer:

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

Tu puedes hacer

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

Solo si su navegador es compatible con ECMAScript 5. Por ejemplo, IE 8 no es compatible con esta función.

Consulte http://kangax.github.io/compat-table/es5/ para obtener más información

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

una versión más limpia de esto podría ser:

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

donde el resultado será indefinido si no se establece ninguna propiedad de objeto.

n0mad
fuente
6

O, si usa lo-dash: _.empty (valor).

"Comprueba si el valor está vacío. Las matrices, cadenas o argumentos, objetos con una longitud de 0 y objetos sin propiedades enumerables propias se consideran" vacíos "."

Jeff Pace
fuente
-2

Comprobar objeto vacío

$scope.isValid = function(value) {
    return !value
}
Taran
fuente
eso está mal. Los objetos vacíos no se pueden probar de esa manera
Kaiser
-11

puedes comprobar la longitud de los artículos

ng-show="items.length"
Pradip Chongbang
fuente
1
No entiendo por qué esta respuesta tiene -1 votos. ¿Alguien puede explicarme eso por favor?
iluu
14
@KarolinaKafel porque itemses un objeto y los objetos no tienen .lengthpropiedad (generalmente) - las matrices las tienen
llamerr
2
No es un tipo de matriz :)
Ghazanfar Khan
@KarolinaKafel no es una matriz, entonces items.length siempre es indefinido.
Fabricio
Ya, ese humano se equivocó, -1 también habría demostrado que esta respuesta es incorrecta, ¿por qué -10? la gente crece :)
Aadam