Reputation: 2946
In the .ts files of an Angular5 project I needed to know the name of the html that was adding the component (for the sake of creating unique names for some buttons inside those components) So my html has ended being something along the lines of:
<my-component data-myattribute="thishtmlfile" ></my-component>
and then I used @Input
on the .ts side to grab this value
But I was wondering if there is a way to automatically know the name of the html my component is being called from, inside the code of the component itself.
The Reflect
object didn't work well for me, but I'm open to try again ;)
Upvotes: 0
Views: 250
Reputation:
I have made something similar to give my HTML elements unique IDs. Here it is, if it can be of any help :
import { AfterViewInit, Directive, ElementRef, Input, Renderer2 } from '@angular/core';
@Directive({
// tslint:disable-next-line:directive-selector
selector: '[app-path]'
})
export class AppPathDirective implements AfterViewInit {
@Input('app-path') path: string & string[];
@Input('app-path.ignoreWarning') private _ignoreWarning = false;
get shouldWarn() {
return this._ignoreWarning === false;
}
element: HTMLElement;
constructor(
private renderer: Renderer2,
el: ElementRef<HTMLElement>,
) {
this.element = el.nativeElement;
if (this.element.id) {
if (this.shouldWarn) {
console.warn(`Custom business error`);
}
}
}
ngAfterViewInit() {
this.setElementCustomId();
}
setElementCustomId() {
let name = '';
// Crawl up to the parent feature with the renderer
let currentElement: HTMLElement = this.element;
while (currentElement && currentElement.tagName && !currentElement.tagName.toLowerCase().startsWith('app-')) {
currentElement = this.renderer.parentNode(currentElement);
}
if (currentElement && currentElement.tagName) {
name += currentElement.tagName.toLowerCase()
// remove 'app-'
.replace('app-', '') + '-';
} else {
if (this.shouldWarn) {
console.warn(`Custom error : No parent feature tag has been found : the name of the feature won't appear in the ID`);
}
}
// Append the HTML component type to the name
const htmlElementName: string = this.element.constructor.name.toLowerCase();
if (!htmlElementName.includes('html') || !htmlElementName.includes('element')) {
// If it is not an HTML element, do nothing and throw an error
if (this.shouldWarn) {
console.warn(`Custom error : No HTML Element was found for the app-path : the element type won't appear in the ID`);
}
} else if (htmlElementName === 'htmlelement') {
// Custom Angular / Material element : ignore.
} else {
// Else, append the element type
name += htmlElementName.replace(/(html|element)/g, '');
}
// Append the custom suffix to the name
let customSuffixe = '';
if (typeof this.path === 'string' && this.path) {
customSuffixe += '-' + this.path;
} else if (this.path && this.path.length) {
this.path.forEach(item => customSuffixe += '-' + item);
}
name += customSuffixe;
this.renderer.setAttribute(this.element, 'id', name);
}
}
This creates a custom name based on the current component you're in, the HTML element targeted by your directive, and some custom suffix you can append to the directive.
Upvotes: 1