Introduction
Here I will create an example on how to check/uncheck individual/all checkbox on HTML table rows. You might have seen how to display data from server using Angular and alternate row color using CSS.
I will put checkbox against each row on the table so that user will be able to select a particular row. I will also put a checkbox on the table header and selecting this checkbox all rows on the table will be selected.
If user selects manually all checkboxes for rows on the table then the checkbox in table header will be checked automatically to show that all checkboxes on the table body are checked. If any of the checkboxes on the table body gets unchecked the header checkbox will be unchecked automatically.
Prerequisites
Angular 9/13, Node 16.12.0, Npm 8.1.0, CSS, HTML, REST API Endpoint – /products
Project Setup
Execute the command ng new angular-check-uncheck-individual-all-checkbox-table-rows
in CLI tool to create a new angular project.
Model Class
I will map JSON object from the server into client side object. The class file product.ts is created under src/app folder.
Therefore I am creating a class called Product which has below attributes:
export class Product {
id?: number;
name: string;
code: string;
price: number;
checked?: boolean;
}
The class is straight forward and notice ?
, which indicates optional value for id
and checked
fields.
Generally ?
is not required on id
field when you are fetching data from server but may be required when you want to save data if you are generating id value on server side.
The checked
field indicates whether a particular checkbox is checked/selected or not.
In Angular 13, I am using interface instead of class for model.
export interface Product {
id?: number;
name: string;
code: string;
price: number;
checked?: boolean;
}
Service Class
Service class is required to process your business logic. The class file product.service.ts is created under src/app folder.
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Product } from './product';
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};
@Injectable({ providedIn: 'root' })
export class ProductService {
private productUrl = 'http://localhost:8080'; // URL to REST API
constructor(private http: HttpClient) { }
/** GET products from the server */
getProducts(): Observable<Product[]> {
return this.http.get<Product[]>(this.productUrl + '/products');
}
}
Notice I have used @Injectable({ providedIn: 'root' })
to make the service class singleton.
A singleton service is a service for which only one instance exists in an app.
There are two ways to make a service a singleton in Angular:
- Set the providedIn property of the @Injectable() to “root”.
- Include the service in the AppModule or in a module that is only imported by the AppModule (explained later).
Change Page Title Globally
I will replace the title in the file src/index.html with the below title:
<title>Angular Check/Uncheck Individual/All Checkbox on HTML Table Rows</title>
If you want to change title for specific title then you have set in the corresponding *.component.ts file.
Load Required Module Globally
I need to import required modules, such as, HttpClientModule
and FormsModule
into the file src/app/app.module.ts file.
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
FormsModule,
BrowserModule,
HttpClientModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
I discussed about making service class singleton and I could have included the ProductService
class into the above file inside provides: []
, such as, providers: [ProductService]
.
Load Data into Component
In order to display data on HTML file I need to load data into corresponding component TypeScript file. So here I have only app component, so I am going to use app.component.ts file under src/app directory.
I have also created to check individual or all checkbox are checked/selected or not.
import { Component, OnInit } from '@angular/core';
import { Product } from './product';
import { ProductService } from './product.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
products: Product[] = [];
constructor(private productService: ProductService) { }
ngOnInit() {
this.getProducts();
}
getProducts(): void {
this.productService.getProducts().subscribe(products => this.products = products);
}
//checkAllCheckBox(ev) { // Angular 9
checkAllCheckBox(ev: any) { // Angular 13
this.products.forEach(x => x.checked = ev.target.checked)
}
isAllCheckBoxChecked() {
return this.products.every(p => p.checked);
}
}
Display Data on HTML Table
Now I will display data on HTML table and provide the checkbox to check/select rows on HTML table.
<h1>Angular Check/Uncheck Individual/All Checkbox on HTML Table Rows</h1>
<div *ngIf="products; else elseBlock">
<table class="datatable">
<thead>
<tr>
<th><input type="checkbox" [checked]="isAllCheckBoxChecked()" (change)="checkAllCheckBox($event)"></th>
<th>ID</th>
<th>Code</th>
<th>Name</th>
<th>Price</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let p of products; let i=index; let odd = odd" [ngClass]="odd ? 'odd_col' : 'even_col'">
<td><input type="checkbox" value="{{p.id}}" [(ngModel)]="products[i].checked"></td>
<td>{{ p.id }}</td>
<td>{{ p.name }}</td>
<td>{{ p.code }}</td>
<td>{{ p.price }}</td>
</tr>
</tbody>
</table>
</div>
<ng-template #elseBlock>No record found</ng-template>
Apply Style
Apply basic style on table and two different colors for alternate rows.
table.datatable {
width:100%;
border: none;
background:#fff;
}
table.datatable td.table_foot {
border: none;
background: #fff;
text-align: center;
}
table.datatable tr.odd_col {
background: none;
}
table.datatable tr.even_col {
background: #ddd;
}
table.datatable td {
font-size:10pt;
padding:5px 10px;
text-align: left;
}
table.datatable th {
text-align: left;
font-size: 8pt;
padding: 10px 10px 7px;
text-transform: uppercase;
color: #fff;
background-color: black;
font-family: sans-serif;
}
Testing the Application
Finally execute the command ng serve --open
on project’s root directory to run the application and the application opens up automatically in the browser at http://localhost:4200.
The below youtube video shows how it works.
Very helpful, thank you.