ngx-router-outlet-class
Version:
A directive to add CSS class(es) to the activated/attached component's host element (hereinafter, the `route element`) of a router-outlet.
95 lines • 13.1 kB
JavaScript
import { Directive, Input, Self } from '@angular/core';
import { merge, tap } from 'rxjs';
import * as i0 from "@angular/core";
import * as i1 from "@angular/router";
export class NgxRouterOutletClassDirective {
constructor(routerOutlet) {
this.routerOutlet = routerOutlet;
/**
* A function to get the class(es) for a specific router-outlet's component's host element.
* The function is called with the component instance as the only argument every time
* the component changes.
* The function should return a string with the class(es) to add.
* Multiple classes can be separated by spaces.
* @type {function}
* @memberof NgxRouterOutletClassDirective
*/
this.dynamicClassGetter = () => '';
this.componentClassList = this.routerOutlet['activated']?.location?.nativeElement.classList;
this.classArray = [];
this.subscription = merge(routerOutlet?.activateEvents, routerOutlet?.attachEvents).pipe(tap(() => this.componentClassList =
this.routerOutlet['activated']?.location?.nativeElement.classList)).subscribe({
next: (component) => {
this.setComponentClass();
const dynamicClasses = this.splitClasses(this.dynamicClassGetter?.(component));
if (dynamicClasses) {
this.setComponentClass(dynamicClasses);
}
},
});
}
/**
* Split a string of classes into an array of classes.
* @param classes A string of classes separated by spaces.
* @private
*/
splitClasses(classes) {
return classes?.split(' ').filter(Boolean) || [];
}
/**
* Set the component class(es) to the component's host element.
* @param classes
* @private
*/
setComponentClass(classes = this.classArray) {
classes.forEach((className) => {
if (!this.componentClassList?.contains(className)) {
this.componentClassList?.add(className);
}
});
}
/**
* Unset the component class(es) from the component's host element.
* @param classes
* @private
*/
unsetComponentClass(classes) {
classes.forEach((className) => {
if (this.componentClassList?.contains(className)) {
this.componentClassList?.remove(className);
}
});
}
ngOnChanges(changes) {
const componentClassChange = changes['componentClass'];
if (componentClassChange) {
const { currentValue, previousValue } = componentClassChange;
const previousClasses = this.splitClasses(previousValue);
const newClasses = this.splitClasses(currentValue);
this.classArray = newClasses;
const notIn = (target) => (str) => !target.includes(str);
const classesToRemove = previousClasses.filter(notIn(newClasses));
const classesToAdd = newClasses.filter(notIn(previousClasses));
this.unsetComponentClass(classesToRemove);
this.setComponentClass(classesToAdd);
}
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
NgxRouterOutletClassDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.3", ngImport: i0, type: NgxRouterOutletClassDirective, deps: [{ token: i1.RouterOutlet, self: true }], target: i0.ɵɵFactoryTarget.Directive });
NgxRouterOutletClassDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.3", type: NgxRouterOutletClassDirective, selector: "router-outlet[componentClass], router-outlet[dynamicClassGetter]", inputs: { componentClass: "componentClass", dynamicClassGetter: "dynamicClassGetter" }, usesOnChanges: true, ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.3", ngImport: i0, type: NgxRouterOutletClassDirective, decorators: [{
type: Directive,
args: [{
selector: 'router-outlet[componentClass], router-outlet[dynamicClassGetter]',
}]
}], ctorParameters: function () { return [{ type: i1.RouterOutlet, decorators: [{
type: Self
}] }]; }, propDecorators: { componentClass: [{
type: Input
}], dynamicClassGetter: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LXJvdXRlci1vdXRsZXQtY2xhc3MuZGlyZWN0aXZlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXJvdXRlci1vdXRsZXQtY2xhc3Mvc3JjL2xpYi9uZ3gtcm91dGVyLW91dGxldC1jbGFzcy5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQXdCLElBQUksRUFBaUIsTUFBTSxlQUFlLENBQUM7QUFHNUYsT0FBTyxFQUFFLEtBQUssRUFBZ0IsR0FBRyxFQUFFLE1BQU0sTUFBTSxDQUFDOzs7QUFLaEQsTUFBTSxPQUFPLDZCQUE2QjtJQUV4QyxZQUNrQixZQUEwQjtRQUExQixpQkFBWSxHQUFaLFlBQVksQ0FBYztRQWdDNUM7Ozs7Ozs7O1dBUUc7UUFDTSx1QkFBa0IsR0FBK0IsR0FBRyxFQUFFLENBQUMsRUFBRSxDQUFDO1FBRTNELHVCQUFrQixHQUFpQixJQUFJLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQyxFQUFFLFFBQVEsRUFBRSxhQUFhLENBQUMsU0FBUyxDQUFDO1FBRXJHLGVBQVUsR0FBYSxFQUFFLENBQUM7UUEzQ2hDLElBQUksQ0FBQyxZQUFZLEdBQUcsS0FBSyxDQUN2QixZQUFZLEVBQUUsY0FBYyxFQUM1QixZQUFZLEVBQUUsWUFBWSxDQUMzQixDQUFDLElBQUksQ0FDSixHQUFHLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLGtCQUFrQjtZQUMvQixJQUFJLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQyxFQUFFLFFBQVEsRUFBRSxhQUFhLENBQUMsU0FBUyxDQUFDLENBQ3JFLENBQUMsU0FBUyxDQUFDO1lBQ1YsSUFBSSxFQUFFLENBQUMsU0FBUyxFQUFFLEVBQUU7Z0JBQ2xCLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO2dCQUV6QixNQUFNLGNBQWMsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUN0QyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO2dCQUN4QyxJQUFJLGNBQWMsRUFBRTtvQkFDbEIsSUFBSSxDQUFDLGlCQUFpQixDQUFDLGNBQWMsQ0FBQyxDQUFDO2lCQUN4QztZQUNILENBQUM7U0FDRixDQUFDLENBQUM7SUFDTCxDQUFDO0lBOEJEOzs7O09BSUc7SUFDSyxZQUFZLENBQUMsT0FBZ0I7UUFDbkMsT0FBTyxPQUFPLEVBQUUsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDbkQsQ0FBQztJQUVEOzs7O09BSUc7SUFDSyxpQkFBaUIsQ0FBQyxVQUFvQixJQUFJLENBQUMsVUFBVTtRQUMzRCxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsU0FBUyxFQUFFLEVBQUU7WUFDNUIsSUFBSSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxRQUFRLENBQUMsU0FBUyxDQUFDLEVBQUU7Z0JBQ2pELElBQUksQ0FBQyxrQkFBa0IsRUFBRSxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUM7YUFDekM7UUFDSCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ssbUJBQW1CLENBQUMsT0FBaUI7UUFDM0MsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLFNBQVMsRUFBRSxFQUFFO1lBQzVCLElBQUksSUFBSSxDQUFDLGtCQUFrQixFQUFFLFFBQVEsQ0FBQyxTQUFTLENBQUMsRUFBRTtnQkFDaEQsSUFBSSxDQUFDLGtCQUFrQixFQUFFLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQzthQUM1QztRQUNILENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELFdBQVcsQ0FBQyxPQUFzQjtRQUNoQyxNQUFNLG9CQUFvQixHQUFHLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBRXZELElBQUksb0JBQW9CLEVBQUU7WUFDeEIsTUFBTSxFQUFFLFlBQVksRUFBRSxhQUFhLEVBQUUsR0FHakMsb0JBQW9CLENBQUM7WUFFekIsTUFBTSxlQUFlLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUN6RCxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ25ELElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDO1lBRTdCLE1BQU0sS0FBSyxHQUFHLENBQUMsTUFBZ0IsRUFBRSxFQUFFLENBQUMsQ0FBQyxHQUFXLEVBQUUsRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUMzRSxNQUFNLGVBQWUsR0FBRyxlQUFlLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO1lBQ2xFLE1BQU0sWUFBWSxHQUFHLFVBQVUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUM7WUFFL0QsSUFBSSxDQUFDLG1CQUFtQixDQUFDLGVBQWUsQ0FBQyxDQUFDO1lBQzFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLENBQUMsQ0FBQztTQUN0QztJQUNILENBQUM7SUFFRCxXQUFXO1FBQ1QsSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUNsQyxDQUFDOzswSEEvR1UsNkJBQTZCOzhHQUE3Qiw2QkFBNkI7MkZBQTdCLDZCQUE2QjtrQkFIekMsU0FBUzttQkFBQztvQkFDVCxRQUFRLEVBQUUsa0VBQWtFO2lCQUM3RTs7MEJBSUksSUFBSTs0Q0E4QkUsY0FBYztzQkFBdEIsS0FBSztnQkFXRyxrQkFBa0I7c0JBQTFCLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBEaXJlY3RpdmUsIElucHV0LCBPbkNoYW5nZXMsIE9uRGVzdHJveSwgU2VsZiwgU2ltcGxlQ2hhbmdlcyB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgUm91dGVyT3V0bGV0IH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcblxuaW1wb3J0IHsgbWVyZ2UsIFN1YnNjcmlwdGlvbiwgdGFwIH0gZnJvbSAncnhqcyc7XG5cbkBEaXJlY3RpdmUoe1xuICBzZWxlY3RvcjogJ3JvdXRlci1vdXRsZXRbY29tcG9uZW50Q2xhc3NdLCByb3V0ZXItb3V0bGV0W2R5bmFtaWNDbGFzc0dldHRlcl0nLFxufSlcbmV4cG9ydCBjbGFzcyBOZ3hSb3V0ZXJPdXRsZXRDbGFzc0RpcmVjdGl2ZSBpbXBsZW1lbnRzIE9uQ2hhbmdlcywgT25EZXN0cm95IHtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBAU2VsZigpIHByaXZhdGUgcm91dGVyT3V0bGV0OiBSb3V0ZXJPdXRsZXQsXG4gICkge1xuICAgIHRoaXMuc3Vic2NyaXB0aW9uID0gbWVyZ2UoXG4gICAgICByb3V0ZXJPdXRsZXQ/LmFjdGl2YXRlRXZlbnRzLFxuICAgICAgcm91dGVyT3V0bGV0Py5hdHRhY2hFdmVudHMsXG4gICAgKS5waXBlKFxuICAgICAgdGFwKCgpID0+IHRoaXMuY29tcG9uZW50Q2xhc3NMaXN0ID1cbiAgICAgICAgdGhpcy5yb3V0ZXJPdXRsZXRbJ2FjdGl2YXRlZCddPy5sb2NhdGlvbj8ubmF0aXZlRWxlbWVudC5jbGFzc0xpc3QpLFxuICAgICkuc3Vic2NyaWJlKHtcbiAgICAgIG5leHQ6IChjb21wb25lbnQpID0+IHtcbiAgICAgICAgdGhpcy5zZXRDb21wb25lbnRDbGFzcygpO1xuXG4gICAgICAgIGNvbnN0IGR5bmFtaWNDbGFzc2VzID0gdGhpcy5zcGxpdENsYXNzZXMoXG4gICAgICAgICAgdGhpcy5keW5hbWljQ2xhc3NHZXR0ZXI/Lihjb21wb25lbnQpKTtcbiAgICAgICAgaWYgKGR5bmFtaWNDbGFzc2VzKSB7XG4gICAgICAgICAgdGhpcy5zZXRDb21wb25lbnRDbGFzcyhkeW5hbWljQ2xhc3Nlcyk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGNsYXNzKGVzKSB0byBhZGQgdG8gdGhlIHJvdXRlci1vdXRsZXQncyBldmVyeSBjb21wb25lbnQncyBob3N0IGVsZW1lbnQuXG4gICAqIE11bHRpcGxlIGNsYXNzZXMgY2FuIGJlIHNlcGFyYXRlZCBieSBzcGFjZXMuXG4gICAqIEl0IHdpbGwgYmUgYXBwbGllZCB0byB0aGUgY29tcG9uZW50J3MgaG9zdCBlbGVtZW50IGV2ZXJ5IHRpbWUgaXRzIHZhbHVlIGNoYW5nZXNcbiAgICogb3IgdGhlIGNvbXBvbmVudCBjaGFuZ2VzLlxuICAgKiBXZSByZWNvbW1lbmQgdXNpbmcgdGhpcyBpbnB1dCBmb3Igc3RhdGljIGNsYXNzZXMgZm9yIGJldHRlciBwZXJmb3JtYW5jZS5cbiAgICogQHR5cGUge3N0cmluZ31cbiAgICogQG1lbWJlcm9mIE5neFJvdXRlck91dGxldENsYXNzRGlyZWN0aXZlXG4gICAqL1xuICBASW5wdXQoKSBjb21wb25lbnRDbGFzcz86IHN0cmluZztcblxuICAvKipcbiAgICogQSBmdW5jdGlvbiB0byBnZXQgdGhlIGNsYXNzKGVzKSBmb3IgYSBzcGVjaWZpYyByb3V0ZXItb3V0bGV0J3MgY29tcG9uZW50J3MgaG9zdCBlbGVtZW50LlxuICAgKiBUaGUgZnVuY3Rpb24gaXMgY2FsbGVkIHdpdGggdGhlIGNvbXBvbmVudCBpbnN0YW5jZSBhcyB0aGUgb25seSBhcmd1bWVudCBldmVyeSB0aW1lXG4gICAqIHRoZSBjb21wb25lbnQgY2hhbmdlcy5cbiAgICogVGhlIGZ1bmN0aW9uIHNob3VsZCByZXR1cm4gYSBzdHJpbmcgd2l0aCB0aGUgY2xhc3MoZXMpIHRvIGFkZC5cbiAgICogTXVsdGlwbGUgY2xhc3NlcyBjYW4gYmUgc2VwYXJhdGVkIGJ5IHNwYWNlcy5cbiAgICogQHR5cGUge2Z1bmN0aW9ufVxuICAgKiBAbWVtYmVyb2YgTmd4Um91dGVyT3V0bGV0Q2xhc3NEaXJlY3RpdmVcbiAgICovXG4gIEBJbnB1dCgpIGR5bmFtaWNDbGFzc0dldHRlcjogKGNvbXBvbmVudDogYW55KSA9PiBzdHJpbmcgPSAoKSA9PiAnJztcblxuICBwcml2YXRlIGNvbXBvbmVudENsYXNzTGlzdDogRE9NVG9rZW5MaXN0ID0gdGhpcy5yb3V0ZXJPdXRsZXRbJ2FjdGl2YXRlZCddPy5sb2NhdGlvbj8ubmF0aXZlRWxlbWVudC5jbGFzc0xpc3Q7XG5cbiAgcHJpdmF0ZSBjbGFzc0FycmF5OiBzdHJpbmdbXSA9IFtdO1xuXG4gIHByaXZhdGUgc3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb247XG5cbiAgLyoqXG4gICAqIFNwbGl0IGEgc3RyaW5nIG9mIGNsYXNzZXMgaW50byBhbiBhcnJheSBvZiBjbGFzc2VzLlxuICAgKiBAcGFyYW0gY2xhc3NlcyBBIHN0cmluZyBvZiBjbGFzc2VzIHNlcGFyYXRlZCBieSBzcGFjZXMuXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBwcml2YXRlIHNwbGl0Q2xhc3NlcyhjbGFzc2VzPzogc3RyaW5nKSB7XG4gICAgcmV0dXJuIGNsYXNzZXM/LnNwbGl0KCcgJykuZmlsdGVyKEJvb2xlYW4pIHx8IFtdO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCB0aGUgY29tcG9uZW50IGNsYXNzKGVzKSB0byB0aGUgY29tcG9uZW50J3MgaG9zdCBlbGVtZW50LlxuICAgKiBAcGFyYW0gY2xhc3Nlc1xuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcHJpdmF0ZSBzZXRDb21wb25lbnRDbGFzcyhjbGFzc2VzOiBzdHJpbmdbXSA9IHRoaXMuY2xhc3NBcnJheSkge1xuICAgIGNsYXNzZXMuZm9yRWFjaCgoY2xhc3NOYW1lKSA9PiB7XG4gICAgICBpZiAoIXRoaXMuY29tcG9uZW50Q2xhc3NMaXN0Py5jb250YWlucyhjbGFzc05hbWUpKSB7XG4gICAgICAgIHRoaXMuY29tcG9uZW50Q2xhc3NMaXN0Py5hZGQoY2xhc3NOYW1lKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVbnNldCB0aGUgY29tcG9uZW50IGNsYXNzKGVzKSBmcm9tIHRoZSBjb21wb25lbnQncyBob3N0IGVsZW1lbnQuXG4gICAqIEBwYXJhbSBjbGFzc2VzXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBwcml2YXRlIHVuc2V0Q29tcG9uZW50Q2xhc3MoY2xhc3Nlczogc3RyaW5nW10pIHtcbiAgICBjbGFzc2VzLmZvckVhY2goKGNsYXNzTmFtZSkgPT4ge1xuICAgICAgaWYgKHRoaXMuY29tcG9uZW50Q2xhc3NMaXN0Py5jb250YWlucyhjbGFzc05hbWUpKSB7XG4gICAgICAgIHRoaXMuY29tcG9uZW50Q2xhc3NMaXN0Py5yZW1vdmUoY2xhc3NOYW1lKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpIHtcbiAgICBjb25zdCBjb21wb25lbnRDbGFzc0NoYW5nZSA9IGNoYW5nZXNbJ2NvbXBvbmVudENsYXNzJ107XG5cbiAgICBpZiAoY29tcG9uZW50Q2xhc3NDaGFuZ2UpIHtcbiAgICAgIGNvbnN0IHsgY3VycmVudFZhbHVlLCBwcmV2aW91c1ZhbHVlIH06IHtcbiAgICAgICAgY3VycmVudFZhbHVlPzogc3RyaW5nLFxuICAgICAgICBwcmV2aW91c1ZhbHVlPzogc3RyaW5nLFxuICAgICAgfSA9IGNvbXBvbmVudENsYXNzQ2hhbmdlO1xuXG4gICAgICBjb25zdCBwcmV2aW91c0NsYXNzZXMgPSB0aGlzLnNwbGl0Q2xhc3NlcyhwcmV2aW91c1ZhbHVlKTtcbiAgICAgIGNvbnN0IG5ld0NsYXNzZXMgPSB0aGlzLnNwbGl0Q2xhc3NlcyhjdXJyZW50VmFsdWUpO1xuICAgICAgdGhpcy5jbGFzc0FycmF5ID0gbmV3Q2xhc3NlcztcblxuICAgICAgY29uc3Qgbm90SW4gPSAodGFyZ2V0OiBzdHJpbmdbXSkgPT4gKHN0cjogc3RyaW5nKSA9PiAhdGFyZ2V0LmluY2x1ZGVzKHN0cik7XG4gICAgICBjb25zdCBjbGFzc2VzVG9SZW1vdmUgPSBwcmV2aW91c0NsYXNzZXMuZmlsdGVyKG5vdEluKG5ld0NsYXNzZXMpKTtcbiAgICAgIGNvbnN0IGNsYXNzZXNUb0FkZCA9IG5ld0NsYXNzZXMuZmlsdGVyKG5vdEluKHByZXZpb3VzQ2xhc3NlcykpO1xuXG4gICAgICB0aGlzLnVuc2V0Q29tcG9uZW50Q2xhc3MoY2xhc3Nlc1RvUmVtb3ZlKTtcbiAgICAgIHRoaXMuc2V0Q29tcG9uZW50Q2xhc3MoY2xhc3Nlc1RvQWRkKTtcbiAgICB9XG4gIH1cblxuICBuZ09uRGVzdHJveSgpIHtcbiAgICB0aGlzLnN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICB9XG5cbn1cbiJdfQ==