97

I want to check if my object is empty dont render my element, and this is my code:

<div class="comeBack_up" *ngIf="previous_info != {}">
  <a [routerLink]="['Inside_group_page',{'name':previous_info.path | dotTodash }]">
    {{ previous_info.title }}
  </a>
</div>

but my code is wrong, what is the best way to do this?

Raphaël Balet
  • 6,334
  • 6
  • 41
  • 78
  • I'm still using a custom function for that.. http://stackoverflow.com/a/33319704/3779853 (defined as an `export`ed function somewhere) – phil294 Jan 28 '17 at 20:38
  • Hugely important question. If a JSON object of data is returned for a component/screen, ngFor/loop thru it and display it. If JSON object is empty, display different screen. – Andrew Koper Sep 19 '18 at 15:21
  • try=> *ngIf="myVar?.length" – raw_hitt May 14 '22 at 10:00

8 Answers8

167

This should do what you want:

<div class="comeBack_up" *ngIf="(previous_info | json) != ({} | json)">

or shorter

<div class="comeBack_up" *ngIf="(previous_info | json) != '{}'">

Each {} creates a new instance and ==== comparison of different objects instances always results in false. When they are convert to strings === results to true

Plunker example

Rahul Kumar
  • 5,120
  • 5
  • 33
  • 44
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
68

From the above answeres, following did not work or less preferable:

  • (previous_info | json) != '{}' works only for {} empty case, not for null or undefined case
  • Object.getOwnPropertyNames(previous_info).length also did not work, as Object is not accessible in the template
  • I would not like to create a dedicated variable this.objectLength = Object.keys(this.previous_info).length !=0;
  • I would not like to create a dedicated function

    isEmptyObject(obj) {
       return (obj && (Object.keys(obj).length === 0));
    }
    

Solution: keyvalue pipe along with ?. (safe navigation operator); and it seems simple.

It works well when previous_info = null or previous_info = undefined or previous_info = {} and treats as falsy value.

<div  *ngIf="(previous_info | keyvalue)?.length">

keyvalue - Transforms Object or Map into an array of key value pairs.

?. - The Angular safe navigation operator (?.) is a fluent and convenient way to guard against null and undefined

DEMO: demo with angular 9, though it works for previous versions as well

Sumit
  • 801
  • 7
  • 12
  • 4
    I think this is the best solution, since putting the function: isEmptyObject() in your template causes it to be called whenever change detection occurs. I've found this to happen quite a bit, such as simply clicking anywhere on the page. – jalbr74 Aug 23 '19 at 14:43
  • 1
    `keyvalue)?.length` does not work: Identifier 'length' is not defined. 'null' does not contain such a member – marcel May 12 '20 at 08:24
  • @marcel could you show your code sample? Because, the Angular safe navigation operator, ?, guards against null and undefined values in property paths. – Sumit May 13 '20 at 13:06
  • @Sumit `*ngIf="({} | keyvalue)?.length"` -> shows the error. I am using Angular 9. – marcel May 14 '20 at 08:52
  • @marcel please check this working demo https://stackblitz.com/edit/angular-ivy-7d27dl?file=src%2Fapp%2Fapp.component.html You can also share a reproducible link. – Sumit May 14 '20 at 22:51
  • @Sumit Weird. Don't know why I get this error then. But it works fine with `json`-pipe. So I currently have no need to change it. – marcel May 19 '20 at 08:14
  • 1
    This is brilliant, a much more elegant solution than converting to string to make a comparison IMO. Thank you! – tpartee Jun 22 '20 at 22:09
43

You could also use something like that:

<div class="comeBack_up" *ngIf="isEmptyObject(previous_info)"  >

with the isEmptyObject method defined in your component:

isEmptyObject(obj) {
  return (obj && (Object.keys(obj).length === 0));
}
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
15

Above answers are okay. But I have found a really nice option to use following in the view:

{{previous_info?.title}}

probably duplicated question Angular2 - error if don't check if {{object.field}} exists

Community
  • 1
  • 1
Damiani
  • 259
  • 3
  • 7
  • 5
    This works if you're absolutely sure the object's gonna have a `title` prop in its non-empty state – Amit May 28 '17 at 09:06
4

This worked for me:

Check the length property and use ? to avoid undefined errors.

So your example would be:

<div class="comeBack_up" *ngIf="previous_info?.length">

UPDATE

The length property only exists on arrays. Since the question was about objects, use Object.getOwnPropertyNames(obj) to get an array of properties from the object. The example becomes:

<div class="comeBack_up" *ngIf="previous_info  && Object.getOwnPropertyNames(previous_info).length > 0">

The previous_info && is added to check if the object exists. If it evaluates to true the next statement checks if the object has at least on proporty. It does not check whether the property has a value.

Loke
  • 1,035
  • 1
  • 8
  • 16
2

A bit of a lengthier way (if interested in it):

In your typescript code do this:

this.objectLength = Object.keys(this.previous_info).length != 0;

And in the template:

ngIf="objectLength != 0"
Katana24
  • 8,706
  • 19
  • 76
  • 118
Mukul_Vashistha
  • 106
  • 1
  • 5
0

Just for readability created library ngx-if-empty-or-has-items it will check if an object, set, map or array is not empty. Maybe it will help somebody. It has the same functionality as ngIf (then, else and 'as' syntax is supported).

arrayOrObjWithData = ['1'] || {id: 1}

<h1 *ngxIfNotEmpty="arrayOrObjWithData">
  You will see it
</h1>

 or 
 // store the result of async pipe in variable
 <h1 *ngxIfNotEmpty="arrayOrObjWithData$ | async as obj">
  {{obj.id}}
</h1>

 or

noData = [] || {}
<h1 *ngxIfHasItems="noData">
   You will NOT see it
</h1>
alexKhymenko
  • 5,450
  • 23
  • 40
0

Using an includes statement verifies that the object is neither null or an empty set.

<div class="comeBack_up" *ngIf="!['null','{}'].includes(previous_info | json)">