By Md. Sabuj Sarker | 2/22/2018 | General |Beginners

Working With Objects, ngFor and ngIf in Angular

Working With Objects, ngFor and ngIf in Angular

In the previous article I showed you how to make our application more dynamic with arrays and the ngFor directive. But we displayed our links like plain text instead of hyperlinks. That's not how we work in HTML. In our array we only have links and no link text. So, we need an user friendly link text against every link and we cannot do that with just an array, we need an array of objects of links where we will put link titles under 'title' keys and links under 'link' keys. In this article we will also use conditions to make our application more logic aware.

ngFor and Objects

We discussed about the ngFor directive in our previous article and I hope you have got the idea on how to use it. Let's convert our social_links array into object as discussed above.

class AppComponent {
 name = "Md. Sabuj Sarker";
 profession = "Software Engineer";
 website = "http://sabuj.me";
 social_links = [
   { title: "Facebook", link: "https://facebook.com/SabujXiP" },
   { title: "Twitter", link: "https://twitter.com/SabujXi" },
   { title: "Github", link: "https://github.com/SabujXi" }
 ]

 constructor(){

 }
}

Now, if you go the browser you will not see what you expect. We need to modify our HTML template code.

<h1>My profile</h1>
<b> Hello World </b> <br/>
My name is Md. {{ name }} <br/>
I am a {{ profession }}. <br/>
Do not forget to visit me at: {{ website }} <br/>
My Social Links: <br/>
<ol>
   <li *ngFor="let link_obj of social_links"> <a href="{{ link_obj.link }}"> {{ link_obj.title }} </a> </li>
</ol>

Go to your browser to see the magic happening. So, to interpolate a value from an object you can use object attribute notation inside the template.

In TypeScript it is good practice to declare an interface for pure objects so that they become type safe and we do not accidentally add unnecessary attributes or fields to the objects. Let's do it.

interface ISocialLink{
 title: string;
 link: string;
}

Now we need to tell TypeScript that social_link is an array of objects of type ISocialLink.

social_links: ISocialLink[] = [
   { title: "Facebook", link: "https://facebook.com/SabujXiP" },
   { title: "Twitter", link: "https://twitter.com/SabujXi" },
   { title: "Github", link: "https://github.com/SabujXi" }
 ]

So, our app.component.ts looks like below:

import { Component } from '@angular/core';

interface ISocialLink{
 title: string;
 link: string;
}

@Component({
 selector: 'app-root',
 templateUrl: './app.component.html',
 styleUrls: ['./app.component.css']
})
export class AppComponent {
 name = "Md. Sabuj Sarker";
 profession = "Software Engineer";
 website = "http://sabuj.me";
 social_links: ISocialLink[] = [
   { title: "Facebook", link: "https://facebook.com/SabujXiP" },
   { title: "Twitter", link: "https://twitter.com/SabujXi" },
   { title: "Github", link: "https://github.com/SabujXi" }
 ]

 constructor(){

 }
}

Go to the browser to see if everything is alright. Now, try to add an extra attribute called active to any of the objects in the list, like below.

{ title: "Facebook", link: "https://facebook.com/SabujXiP", active: true }

Go to the command line to see the following error:

ERROR in src/app/app.component.ts(18,65): error TS2322: Type '({ title: string; link: string; active: boolean; } | { title: string; link: string; })[]' is not assignable to type 'ISocialLink[]'.
 Type '{ title: string; link: string; active: boolean; } | { title: string; link: string; }' is not assignable to type 'ISocialLink'.
   Type '{ title: string; link: string; active: boolean; }' is not assignable to type 'ISocialLink'.
     Object literal may only specify known properties, and 'active' does not exist in type 'ISocialLink'.

So, with the use of an interface in TypeScript we can ensure that our code is going to behave like we want.

ngIf

Now, it's time to work with conditions in our template. Before doing that we want to change our link objects and add an extra field called is_active to denote whether the social link is active or not. We need to modify our interface first to declare is_active as a boolean.

import { Component } from '@angular/core';

interface ISocialLink{
 title: string;
 link: string;
 is_active: boolean;
}

@Component({
 selector: 'app-root',
 templateUrl: './app.component.html',
 styleUrls: ['./app.component.css']
})
export class AppComponent {
 name = "Md. Sabuj Sarker";
 profession = "Software Engineer";
 website = "http://sabuj.me";
 social_links: ISocialLink[] = [
   { title: "Facebook", link: "https://facebook.com/SabujXiP", is_active: true },
   { title: "Twitter", link: "https://twitter.com/SabujXi", is_active: false },
   { title: "Github", link: "https://github.com/SabujXi", is_active: true }
 ]

 constructor(){

 }
}

Now our intention is to display the links which are active and show 'This link is not active' for the link objects that have is_active set to true.

Like ngFor, Angular provides another directive called ngIf for checking a condition or the trueness of a value and display or hide (remove from DOM) the tag and it's children on which it is applied. Let's modify our HTML accordingly:

<h1>My profile</h1>
<b> Hello World </b> <br/>
My name is Md. {{ name }} <br/>
I am a {{ profession }}. <br/>
Do not forget to visit me at: {{ website }} <br/>
My Social Links:
<ol>
   <li *ngFor="let link_obj of social_links"> 
       <a *ngIf="link_obj.is_active" href="{{ link_obj.link }}"> {{ link_obj.title }} </a> 

       <span *ngIf="!link_obj.is_active"> <strike> This link is not active </strike> </span>
   </li>
</ol>

Notice that there is no ngElse in Angular, instead we need to use ngIf with a negation operator. There is another way with the Angular ng-template tag to emulate the behavior of else. Here it goes.

<ol>
   <li *ngFor="let link_obj of social_links"> 
       <a *ngIf="link_obj.is_active; else elseTemplate" href="{{ link_obj.link }}"> {{ link_obj.title }} </a> 

       <ng-template #elseTemplate>
           <s> This link is not active </s>
       </ng-template>
   </li>
</ol>

Do you see that weird syntax #elseTemplate there? We declare a template variable with this. What we put after the hash sign inside the opening tag becomes a template variable. We can refer to an element (or optionally what is assigned to that template variable from its scope) in another element inside the template. Be careful about nesting or parent, child and sibling things.

Conclusion

So, we have advanced one step further in our learning of Angular. Now we can use conditions, loops, arrays, objects, interfaces, template reference variables and few other things. We’ll explore more topics in future articles. Till then, keep practicing.

Previous article: Displaying an Array of Elements in an Angular Template

Next article: Property and Attribute Binding in Angular

About the Author

My name is Md. Sabuj Sarker. I am a Software Engineer, Trainer and Writer. I have over 10 years of experience in software development, web design and development, training, writing and some other cool stuff including few years of experience in mobile application development. I am also an open source contributor. Visit my github repository with username SabujXi.

By Md. Sabuj Sarker | 2/22/2018 | General

{{CommentsModel.TotalCount}} Comments

Your Comment

{{CommentsModel.Message}}

Recent Stories

Top DiscoverSDK Experts

User photo
3355
Ashton Torrence
Web and Windows developer
GUI | Web and 11 more
View Profile
User photo
3220
Mendy Bennett
Experienced with Ad network & Ad servers.
Mobile | Ad Networks and 1 more
View Profile
User photo
3060
Karen Fitzgerald
7 years in Cross-Platform development.
Mobile | Cross Platform Frameworks
View Profile
Show All
X

Compare Products

Select up to three two products to compare by clicking on the compare icon () of each product.

{{compareToolModel.Error}}

Now comparing:

{{product.ProductName | createSubstring:25}} X
Compare Now