'Clickable table cells in angular
I have one table with rows. When I click on a cell it has changed color to red but only one at a time can be red. If I click on another cell, the previous cell should no longer be red. I don't know how to make only one cell red at a time. Do you have any ideas?
html file:
<table>
<tr appFocusCell><td > </td></tr>
<tr appFocusCell><td> </td></tr>
<tr appFocusCell><td> </td></tr>
<tr appFocusCell><td> </td></tr>
<tr appFocusCell><td> </td></tr>
<tr appFocusCell><td> </td></tr>
<tr appFocusCell><td></td></tr>
</table>
focus-cell.directive file:
import {Directive, ElementRef, HostListener, Renderer2} from '@angular/core';
@Directive({
selector: '[appFocusCell]'
})
export class FocusCellDirective {
constructor(private e:ElementRef,private render: Renderer2) { }
ngOnInit() {
}
@HostListener('click')
onClick(){
const div = this.e.nativeElement;
this.render.setStyle(div,'background','red')
}
}
Solution 1:[1]
Following is the code sample
html
<table border="1">
<tbody>
<tr>
<td appCellClick>
Cell1.1
</td>
<td appCellClick>
Cell1.2
</td>
</tr>
<tr>
<td appCellClick>
Cell2.1
</td>
<td appCellClick>
Cell2.2
</td>
</tr>
</tbody>
</table>
directive
import { Directive, HostListener, Renderer2 } from '@angular/core';
@Directive({
selector: '[appCellClick]',
})
export class CellClickDirective {
@HostListener('click', ['$event']) onClick(ev) {
const curEl = ev.target; //TAKE CLICKED CELL ELEMENT
let parentEl:any = {};
// CHECK THE PARENT TABLE ELEMENT
const parentChecker = (el) => {
if (el.nodeName == 'TABLE') {
parentEl = el;
} else {
parentChecker(el.parentElement);
}
};
parentChecker(curEl);
// PARENT TABLE FOUND - REMOVE EXISTING CSS-CLASS
if(parentEl){
const addedBg = parentEl.querySelectorAll('td.bg-red');
addedBg.forEach((e) => {
e.setAttribute('class', e.getAttribute('class').replace('bg-red',''));
});
}
this.renderer.addClass(curEl, 'bg-red');
}
constructor(
private renderer: Renderer2
) {}
}
css
.bg-red{
background-color: red;
}
Solution 2:[2]
You might want to add logic about which row is currently selected, by means of creating a parent directive to bookmark the currently clicked row.
The idea is, with information about which row is currently clicked, this parent directive can remove highlight of the old row clicked and highlight the newly clicked row instead.
Here's a sample solution. I have not tested it, but hopefully the idea behind it is clear.
<table appTable> <!-- ? make new directive-->
<tr appFocusCell>...</tr>
<tr appFocusCell>...</tr>
...
</table>
@Directive({
selector: '[appFocusCell]'
})
export class FocusCellDirective implements OnDestroy {
readonly onClick$ = new Subject<void>(); // ? emit when host is clicked
@HostListener('click')
onClick() {
this.onClick$.next();
}
// ? set/unset row background color whether active/inactive
set isActive(isActive: boolean) {
this.e.style.backgroundColor = isActive ? 'red' : 'unset';
}
constructor(private e: ElementRef<HTMLElement>) { }
ngOnDestroy() {
this.onClick$.complete();
}
}
@Directive({
selector: '[appTable]'
})
export class AppTableDirective implements AfterContentInit, OnDestroy {
private clickedRow: FocusCellDirective | null = null; // ? bookmark currently clicked row
@ContentChildren(FocusCellDirective, { descendants: true })
private rows!: QueryList<FocusCellDirective>; // ? get all table rows
private onDestroy = new Subject<void>();
ngAfterContentInit() {
// ? listen to any rows clicked
this.rows.forEach((row) => {
row.onClick$
.pipe(takeUntil(this.onDestroy))
.subscribe(() => this.setClicked(row)); // ? update currently clicked row
});
}
private setClicked(row: FocusCellDirective) {
if(this.clickedRow !== null) {
this.clickedRow.isActive = false; // ? remove highlight of previously clicked row
}
row.isActive = true; // ? highlight currently clicked row
this.clickedRow = row; // ? bookmark currently clicked row
}
ngOnDestroy() {
this.onDestroy.next();
this.onDestroy.complete();
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Nathash Kumar |
| Solution 2 |
