I am looking for a work-around to replace the new Checkbox Check Icon, since angular + primeng updates the icons changed, but I want to use the older version of it.
Please find a minimal reproduction of my issue here.
My idea is to target all <p-checkbox>
with a directive and replace the <checkicon>
somehow.
I tried with viewContainerRef
in the directives constructor, but then viewContainerRef targets the wrong html element (p-checkbox) and the icon is inserted in the wrong place.
@Directive({
selector: 'p-checkbox',
})
export class IconDirective {
constructor(private viewContainerRef: ViewContainerRef) {}
}
Then I tried to target PrimeNGĀ“s checkicon
element directly as that is the place I want to replace the checkicon with my custom icon, but that does not seem to work.
@Directive({
selector: 'checkicon',
})
export class IconDirective {
constructor(private viewContainerRef: ViewContainerRef) {}
@HostListener('click', ['$event']) onModelChange(): void {
setTimeout(() => {
this.replaceCheckIcon();
});
}
async replaceCheckIcon() {
this.viewContainerRef.clear();
this.viewContainerRef.createComponent(CustomIcon);
}
}
Following options won't work for me:
the newly introduced checkboxIcon
property, since I use the pi pi-times
icon, but this icon changed in appearance.
touching / changing any html directly, because in my project there are thousand of checkboxes and I won't add the <ng-template pTemplate="icon">
with my custom icon to all checkbox occurrences.
adding <ng-container #target>
to any of my html to have a viewContainerRef from a ViewChild
query is also not an option, tho adding it programmatically would be an option, but I could not figure it out.
First you need to check if the old icon exists which I used querySelector
, then I remove it using renderer2
's removeChild
method.
Then we can use createComponent
API to create the component. Then add the default primeng classes for the icon using addClass
, then finally using appendChild
insert the new icon where the old icon used to be.
Hope you use this code and suit it to your requirements.
import {
Directive,
ElementRef,
HostListener,
Renderer2,
ViewContainerRef,
createComponent,
Injector,
EnvironmentInjector,
ChangeDetectorRef,
} from '@angular/core';
import { CustomIcon } from './icon/custom-icon';
@Directive({
selector: 'p-checkbox',
})
export class IconDirective {
@HostListener('click', ['$event']) onModelChange(): void {
setTimeout(() => {
this.replaceCheckIcon();
});
}
constructor(
private elementRef: ElementRef,
private viewContainerRef: ViewContainerRef,
private renderer: Renderer2,
private environmentInjector: EnvironmentInjector,
private cdr: ChangeDetectorRef
) {}
replaceCheckIcon() {
const oldIcon = this.elementRef.nativeElement.querySelector('checkicon');
const newIcon = this.elementRef.nativeElement.querySelector('custom-icon');
const checkboxContainer =
this.elementRef.nativeElement.querySelector('.p-checkbox-box');
if (oldIcon) {
this.renderer.removeChild(this.elementRef.nativeElement, oldIcon);
}
if (!newIcon) {
const component = createComponent(CustomIcon, {
environmentInjector: this.environmentInjector,
});
this.renderer.addClass(component.location.nativeElement, 'p-element');
this.renderer.addClass(
component.location.nativeElement,
'p-icon-wrapper'
);
this.renderer.appendChild(
checkboxContainer,
component.location.nativeElement
);
}
}
}