Highlight selected row Angular 2

When you work with tables or lists, you will withstand a situation at some time where you would like to highlight the selected row of  a table or an item on a list. Well, in the article we will Highlight selected row Angular 2.

Angular 2.o was out just a few days ago and is ready for production. If you haven't started yet, I think it's the best time to assail on Angular 2.o.  Angular 2.o comes with a lots of great features, and we will cover them one by one.

 

But in this article, we will go through below topics,

  1. Create Angular 2.0 component using Angular CLI.
  2. Use nested components to create an application.
  3. Send/receive data between two components.

Setting up our Application

We will setup our application with the Angular CLI. If you don't have Angular CLI installed on your machine run the below command to install it globally. Trust me it will make your development super fast.
npm install -g angular-cli
To create a new Angular project Run below command. This command will create all the necessary files, download all the required external dependencies and do all of the setup work for us.

ng new todoApp

Once the ng new todoApp has completed the setup process, go to the todoApp directory you must see the below directory structure.

Highlight selected row Angular 2 directory-structure

The application

In this application, the user will have a list of Todos. When users click on Todo that Row will be selected. We indicate the selected row by changing it's background color.

It's a good practice to divide your Angular application into several component.

Yes, Dividing application into several components will reduce the complexity level of your application in terms of structure. 

Here, our application is not that much complex However let's divide our application.

In the below diagram we have two components. The first component is our root component and the second component will contain the list of todos.

 Highlight selected row Angular 2 applicatio division

Time to create Components

To create Components In Angular application is very easy with the help of Angular CLI. Below command is used to create a component,
ng generate component componentName

In our application, we require two components listed below,

  1. todo component : root component.
  2. todo-list component : renders the list of todos.

Run the below commands in order to achieve this,

  1. To create todo component run : ng generate component todo
  2. To create todo-list component  run : ng generate component todo-list

 

Using the components

Fine, our components are ready to use let's use them open main.ts file located in /src directory. Let's import our component into main.ts and remove default one i.e. AppComponent.
How would our main.ts file look like ?

main.ts:

/*
* Creating Highlight selected row Angular 2 application
* @author Shashank Tiwari 
*/
import { bootstrap } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { environment } from './app/';
import { TodoComponent } from './app/todo/';

if (environment.production) {
  enableProdMode();
}

bootstrap(TodoComponent);

Now open index.html file located in /src directory. Replace selector by <app-todo>. Let's take a look at index.html.

index.html:

<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <title>Todo</title>
    <base href="/">
    <link rel="stylesheet" href="vendor/bootstrap/dist/css/bootstrap.min.css">
    {{#unless environment.production}}
    <script src="/ember-cli-live-reload.js" type="text/javascript"></script>
    {{/unless}}
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
    <app-todo>Loading...</app-todo>
  
    {{#each scripts.polyfills}}
    <script src="{{.}}"></script>
    {{/each}}
    
    <script>
        System.import('system-config.js').then(function () {
            System.import('main');
        }).catch(console.error.bind(console));
    </script>
  
</body>
</html>

In this application, we will show Todo list based on below class. Create a file named as todolistprovider.ts  and write below code.

todolistprovider.ts :

/*
* Creating Highlight selected row Angular 2 application
* @author Shashank Tiwari 
*/
export class TodoListProvider {
    constructor(
    	public name: string,
		public date: number
	) {}
}

Passing Data between two Components

Rendering the list of todos (sending data from parent component to child component):

Here we will send an array of todos from todo-component to todo-list component and we will use that array to render the list of todos.

Open todo-component.ts file write below code, Don't worry I'll explain each and every line. This component will show the main layout.
todo-component.ts:

/*
* Creating Highlight selected row Angular 2 application
* @author Shashank Tiwari 
*/

import { Component } from '@angular/core';
import { TodoListProvider } from './../todolistprovider';
import { TodoListComponent } from './../todo-list-component/';

@Component({
    moduleId: module.id,
    directives: [TodoListComponent],
	selector: 'app-todo',
	templateUrl: 'todo-component.html',
	styleUrls: ['todo-component.css']
})
export class TodoComponent {

	todoListProvider: TodoListProvider[];
	
	constructor() {
		this.todoListProvider = [
			new TodoListProvider('Task 1', Date.now() ),
			new TodoListProvider('Task 2', Date.now() ),
			new TodoListProvider('Task 3', Date.now() ),
			new TodoListProvider('Task 4', Date.now() ),
			new TodoListProvider('Task 5', Date.now() ),
		];
	}
}

Explanation:

1. In the first two lines, we  are importing the TodoListProvider class and todo-list Component to show the list of todos.

2. After that, we have our component decorator. Where we are everything look familiar excluding directives property.

Remember,  a component is nothing but a directive.

This directives property takes an array of classes. This specifies the component we want to be able  to use in the current view. Here we are passing TodoListComponent class in order to use  todo-list Component.

3. In the TodoComponent class have an array of type TodoListProvider, which will be passed to the child component to render the list of todos.

4. Now open our todo-component.html file,write below code. In the below code we are using the <todo-list> selector to render the list of todos.
todo-component.html:

<!-- 
Creating Highlight selected row Angular 2 application
@author Shashank Tiwari 
-->

<div class="container">
    <h2 class="heading">Highlight selected Row in Angular 2.</h2>
    <div class="row">
		<todo-list
			[todoList]="todoListProvider">
		</todo-list>
	</div>
</div>

In the above code, we are using one of the most important features of Angular component i.e inputs and outputs.

1. The [squareBrackets] pass inputs[todoList]="todoListProvider".

Explanation:

  1. Here todoListProvider contains the  list of todos that we send to the todo-list component.
  2. By using todoList we can access the list of todos in the todo-list component.

Rendering the list of todos

Now we have an array of todos, that we can access in the todo-list component.

Let's write code for the todo-list component, open the todo-list-component.ts file located inside /todo-list the directory. This component will render a list of todos. For now  nothing much to see in TodoListComponent class.

todo-list-component.ts:

/*
* Creating Highlight selected row Angular 2 application
* @author Shashank Tiwari 
*/
import { Component, EventEmitter } from '@angular/core';
import { TodoListProvider } from './../todolistprovider';

@Component({
    moduleId: module.id,
    selector: 'todo-list-component',
	inputs: ['todoList'],
	templateUrl: 'todo-list-component.html',
	styleUrls: ['todo-list-component.css']
})

export class TodoListComponent {
	
	constructor() {
		
	}
}

Explanation:

1. In the component decorator, we have one unfamiliar attributes(options) i.e. inputs. We are okay with rest of the attributes, aren't we?

2. We already understood what inputs are. Now let's understand how do we manage this in the component.
inputs : inputs: ['todoList']
Explanation:

  1. inputs takes an array of strings which specify the input keys.
  2. With the inputs option, we’re specifying the parameters we expect our component to receive.
  3. Here todoList acting as input key.

Open todo-list-component.html, write the below code. In the below code, we are using Angular 2's built-in directive (component) called as ngFor.

<!-- 
Creating Highlight selected row Angular 2 application
@author Shashank Tiwari 
-->

<div class="list-of-todos">
    <ul class="list-group">
    	<li *ngFor="let todo of todoList"
			class="list-group-item todo">
			{{ todo.name}}
		</li>
	</ul>
</div>

Now open the CMD, navigate to your application directory and type the below command to run the application.

ng-serve

Go to the localhost:4200you should see the list of todos.

Highlight selected a row

Now our list of todos is ready, let's propel our self ahead to highlight selected a row from the list of todos.

In todo-list-component.html, we will add a click event and class directive to indicate the selection as shown below.
todo-list-component.html:

<!-- 
Creating Highlight selected row Angular 2 application
@author Shashank Tiwari 
-->

<div class="list-of-todos">
    <ul class="list-group">
    	<li *ngFor="let todo of todoList" 
            (click)="selectedTodo(todo)" <!-- click event to handle the selection -->
			[class.active]="isSelected(todo)" <!-- adding a class to indicate the selection -->
			class="list-group-item todo">
			{{ todo.name}}
		</li>
	</ul>
</div>

In the above code,
click event will call selectedTodo() function to match the selected to-do, on the appropriate condition we will add the .active class to the row. So let's take a look at the todo-list component what we have there,
todo-list-component.ts:

/* 
* Creating Highlight selected row Angular 2 application
* @author Shashank Tiwari 
*/
import { Component, EventEmitter } from '@angular/core';
import { TodoListProvider } from './../todolistprovider';

@Component({
    moduleId: module.id,
    selector: 'todo-list-component',
	inputs: ['todoList'],
	templateUrl: 'todo-list-component.html',
	styleUrls: ['todo-list-component.css']
})

export class TodoListComponent {
	
	currentTodo: TodoListProvider;

	constructor() {
	}

	selectedTodo(todo:TodoListProvider):void{
		this.currentTodo = todo;
	}

	isSelected(todo:TodoListProvider): boolean {
		if(!this.currentTodo) {
			return false;
		}
		return this.currentTodo.name ===  todo.name ? true : false;
	}
}

In the above code, we have added one variable and two functions as listed below.

  1. currentTodo : This variable is of type TodoListProvider and hold the currently selected to do.
  2. selectedTodo() : This function expects the object of type TodoListProvider and assigns the value to the currentTodo variable.
  3. isSelected() : This function return true or false based on the condition written inside it and expects the object of type TodoListProvider as a parameter.

Now visit the  localhost:4200 , tell me the output.

Last piece of the puzzle (sending the data from child component to parent component)

To send data from todo-list component to todo component we will use outputs and Event emitters.

Note:
This topic(Event emitter,inputs, and outputs) deserve it's own blog post.For now, am just giving an overview.

Open the todo-list-component.ts and the code by below code. what is happing in the below code anyway,

todo-list-component.ts:

/*
* Creating Highlight selected row Angular 2 application
* @author Shashank Tiwari 
*/


import { Component, EventEmitter } from '@angular/core';
import { TodoListProvider } from './../todolistprovider';

@Component({
    moduleId: module.id,
    selector: 'todo-list-component',
	inputs: ['todoList'],
	outputs: ['onTodoSelected'],
	templateUrl: 'todo-list-component.html',
	styleUrls: ['todo-list-component.css']
})

export class TodoListComponent {
	
	currentTodo: TodoListProvider;
	onTodoSelected: EventEmitter<TodoListProvider>;

	constructor() {
		this.onTodoSelected = new EventEmitter();
	}

	selectedTodo(todo:TodoListProvider):void{
		this.currentTodo = todo;
		this.onTodoSelected.emit(todo);
	}

	isSelected(todo:TodoListProvider): boolean {
		if(!this.currentTodo) {
			return false;
		}
		return this.currentTodo.name ===  todo.name ? true : false;
	}
}

1. If you notice we have outputs attribute(option) in the component decorator.

outputs:  outputs: ['onTodoSelected']
Explanation:

  1. To send data from component we use output bindings.
  2. Here we will use EventEmitter to emit the output by attaching to the outputs property.

2. We have added one more variable onTodoSelected of type TodoListProvider by attaching EventEmitter to it.

3. When we click on the list, EventEmitter emits the event as shown below,
this.onTodoSelected.emit(todo)

Handling the event

Now in todo component we have to catch the event that is emitted by todo-list component.
todo-component.html:

<!-- 
Creating Highlight selected row Angular 2 application
@author Shashank Tiwari 
-->

<div class="container">
    <h2 class="heading">Highlight selected Row in Angular 2.</h2>
    <div class="row">
		<todo-list-component
			[todoList]="todoListProvider" (onTodoSelected)="todoSelected($event)" >
		</todo-list-component>
	</div>
	<h3 class="heading" 
		[ngClass]="todoName == '' ? 'hide-heading' : 'show-heading'"> 
		You selected {{ todoName }}
	</h3>
</div>

Notice that In the above code we have added  (onTodoSelected)="todoSelected($event)".

2. The (parenthesis) handle outputs (onTodoSelected)="todoSelected($event)"
Explanation:

  1. onTodoSelected is the name of the output that we want from the todo-list component.
  2. todoSelected is a function that will be called whenever users change the selection of todos, we will see that in a minute when we talk about our component.
  3. $event a variable used to carry output data.

Let's open todo-component.ts file and replace the code by below code. In the below code we have added one variable named todoName of type String and one function named as todoSelected which takes a parameter of type TodoListProvider.

todo-component.ts:

/*
* Creating Highlight selected row Angular 2 application
* @author Shashank Tiwari 
*/

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

import { TodoListProvider } from './../todolistprovider';
import { TodoListComponentComponent } from './../todo-list-component/';

@Component({
    moduleId: module.id,
    directives: [TodoListComponentComponent],
	selector: 'app-todo-component',
	templateUrl: 'todo-component.component.html',
	styleUrls: ['todo-component.component.css']
})
export class TodoComponentComponent {

	todoListProvider: TodoListProvider[];

	todoName: string; 
	
	constructor() {
		this.todoListProvider = [
			new TodoListProvider('Task 1', Date.now() ),
			new TodoListProvider('Task 2', Date.now() ),
			new TodoListProvider('Task 3', Date.now() ),
			new TodoListProvider('Task 4', Date.now() ),
			new TodoListProvider('Task 5', Date.now() ),
		];

		this.todoName = "";
	}

	todoSelected(todo:TodoListProvider):void{
		this.todoName = todo.name;
	}
}

Final thoughts

That's it for this article. In this article, we went through below topics,

  1. Create Angular 2.0 component using Angular CLI.
  2. Use nested components to create an application.
  3. Send/receive data between two components.

and we also divided our application into components, which is a good practice to follow. If you like this article share with your friends and other people I will be back with a new article very soon.