I have created the following custom directive in Angular:
@Directive({
selector: '[tableTheme]'
})
export class TableThemeDirective implements OnInit, AfterViewInit {
tableElement: HTMLTableElement;
constructor(private el: ElementRef, private renderer: Renderer2) {}
ngOnInit(): void {
this.tableElement = this.el.nativeElement;
this.renderer.setStyle(this.tableElement, 'width', '100%');
this.renderer.setStyle(this.tableElement, 'border-collapse', 'separate');
this.renderer.setStyle(this.tableElement, 'border-spacing', '0 1em');
this.renderer.setStyle(this.tableElement, 'color', 'white');
const thElements: NodeListOf<HTMLTableCellElement> = this.tableElement.querySelectorAll('th');
thElements.forEach((el) => {
this.renderer.setStyle(el, 'height', '2em');
this.renderer.setStyle(el, 'margin-bottom', '1em');
this.renderer.setStyle(el, 'padding', '1em');
});
}
ngAfterViewInit(): void {
const tdElements: NodeListOf<HTMLTableCellElement> = this.tableElement.querySelectorAll('td');
tdElements.forEach((el) => {
this.renderer.setStyle(el, 'background-color', 'var(--primary-clr-light)');
});
let tdFirstChildElements: HTMLTableCellElement[] = [];
let tdLastChildElements: HTMLTableCellElement[] = [];
tdElements.forEach((el) => {
const parentNode: ParentNode = el.parentNode;
if(el === parentNode.firstElementChild) {
tdFirstChildElements.push(el);
} else if(el === parentNode.lastElementChild) {
tdLastChildElements.push(el);
}
});
console.log(tdFirstChildElements);
console.log(tdLastChildElements);
tdFirstChildElements.forEach((el) => {
this.renderer.setStyle(el, 'border-left-style', 'solid');
this.renderer.setStyle(el, 'border-top-left-radius', '10px');
this.renderer.setStyle(el, 'border-bottom-left-radius', '10px');
this.renderer.setStyle(el, 'padding', '1em');
});
tdLastChildElements.forEach((el) => {
this.renderer.setStyle(el, 'border-right-style', 'solid');
this.renderer.setStyle(el, 'border-top-right-radius', '10px');
this.renderer.setStyle(el, 'border-bottom-right-radius', '10px');
this.renderer.setStyle(el, 'padding', '1em');
});
}
}
Then I use this directive to style a table:
<table tableTheme>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Username</th>
<th>Role</th>
<th>Email</th>
<th>Contact Number</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let user of displayingUsers">
<td>{{ user.id }}</td>
<td>{{ user.name }}</td>
<td>{{ user.username }}</td>
<td>{{ user.role }}</td>
<td>{{ user.email }}</td>
<td>{{ user.contactNumber }}</td>
<td>Action</td>
</tr>
</tbody>
</table>
As you can see the directive is attached to the table element.
Then I add some logic for pagination below the table:
<div >
<button
type="button"
*ngFor="let item of createRange(collectionLength); let i = index"
(click)="onPaginationButtonClick(i 1)">
{{ i 1 }}
</button>
</div>
Implementation of the pagination:
export class UsersComponent implements OnInit {
users: User[];
displayingUsers: User[];
currentPage: number = 1;
perPage = 4;
collectionLength: number;
createRange(count: number): number[] {
return new Array(count);
}
onPaginationButtonClick(clickedPage: number): void {
this.displayingUsers = this.users.slice((clickedPage - 1) * this.perPage, (clickedPage - 1) * this.perPage this.perPage);
}
constructor() { }
ngOnInit(): void {
this.users = USERS;
this.onPaginationButtonClick(1);
this.collectionLength = Math.ceil(this.users.length / this.perPage)
}
}
Pagination completely works. But the table looses the style defined in the directive once the pagination buttons are clicked. (Following screenshots shows the problem.)
Before pagination buttons are clicked
After pagination buttons are clicked
As you can see the table loses the styles defined in the directive.
How to keep the styles defined in the directive?
CodePudding user response:
You can use renderer.addClass to add style to the element
ngOnInit(): void {
this.tableElement = this.el.nativeElement;
// add class(table-theme) to the component.css
this.renderer.addClass(this.el.nativeElement, 'table-theme');
}
In HTML, wrap the table inside a div and apply your directive on the div
<div table-theme>
<table>......</table>
<div>
Please find the working solution link below
https://stackblitz.com/edit/angular-ivy-9fqtkq?file=src/app/app.component.ts