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,
- Create Angular 2.0 component using Angular CLI.
- Use nested components to create an application.
- 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 CLIinstalled 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.
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.
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,
todo component
: root component.todo-list component
: renders the list of todos.
Run the below commands in order to achieve this,
- To create todo component run :
ng generate component todo
- 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.
Opentodo-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 theTodoListProvider class andtodo-list Component to show the list of todos.
2. After that, we have our component decorator. Where we are everything look familiar excludingdirectives property.
Remember, a component is nothing but a directive.
Thisdirectives 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 theTodoComponent class have an array of typeTodoListProvider
, 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 inputsand outputs.
1.The [squareBrackets] pass inputs :[todoList]="todoListProvider"
.
Explanation:
- Here todoListProvider contains the list of todos that we send to the todo-list component.
- 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:
- inputs takes an array of strings which specify the input keys.
- With the inputs option, we’re specifying the parameters we expect our component to receive.
- 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 asngFor.
<!-- 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:4200,you 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.
currentTodo
: This variable is of type TodoListProvider and hold the currently selected to do.selectedTodo()
: This function expects the object of type TodoListProvider and assigns the value to thecurrentTodo
variable.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.
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:
- To send data from component we use output bindings.
- 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:
- onTodoSelected is the name of the output that we want from the todo-list component.
- 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.
- $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,
- Create Angular 2.0 component using Angular CLI.
- Use nested components to create an application.
- 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.
import { BrowserModule } from ‘@angular/platform-browser’;
import { NgModule } from ‘@angular/core’;
import { TodoComponent } from ‘./todo/todo.component’;
import { TodoListComponent } from ‘./todo-list/todo-list.component’;
@NgModule({
imports: [
BrowserModule,
TodoComponent,
TodoListComponent
],
declarations: [
TodoComponent
],
providers: [],
bootstrap: [TodoComponent]
})
export class AppModule { }
I got an this error
————
compiler.js:1016 Uncaught Error: Unexpected directive ‘TodoComponent’ imported by the module ‘AppModule’. Please add a @NgModule annotation.