As you've discovered, you can't have a dynamic template in Angular because the templates are bundled with components as javascript. If you want to learn more, check out this issue on github. The upshot of it is: dynamic templates would break AOT compilation.
You have also discovered that you can set the innerHTML
of an object to arbitrary HTML, but routerLink
won't work in that context. Why? Because routerlink
is an Angular directive, not an HTML attribute. Since we are just setting the innerHTML
, it's not a compiled template.
So, what's the solution? Let's back up and think about what routerLink
is doing in the first place. As it turns out, not much. Take a look at the source. Specifically, this is what it's doing when an element with the routerLink
directive is clicked:
@HostListener('click')
onClick(): boolean {
const extras = {
skipLocationChange: attrBoolValue(this.skipLocationChange),
replaceUrl: attrBoolValue(this.replaceUrl),
};
this.router.navigateByUrl(this.urlTree, extras);
return true;
}
It's just using HostListener
to monitor clicks, and routing accordingly. We can do something similar in our component. I've called it FooterComponent
since you mentioned that this was a footer with dynamic HTML:
import { Component, Input, HostListener } from '@angular/core';
import { Router } from '@angular/router';
@Component({
selector: 'app-footer',
template: '<div [innerHTML]="footerHtml"></div>'
})
export class FooterComponent {
@Input() footerHtml: string = "";
constructor(private router: Router) { }
// Watch for clicks in our component
@HostListener("click", ['$event'])
onClick(event: MouseEvent) {
// If we don't have an anchor tag, we don't need to do anything.
if (event.target instanceof HTMLAnchorElement === false) {
return;
}
// Prevent page from reloading
event.preventDefault();
let target = <HTMLAnchorElement>event.target;
// Navigate to the path in the link
this.router.navigate([target.pathname]);
}
}
As you can see, it takes in input called footerHtml
, which is of type string. To use it, we will add this somewhere:
<app-footer [footerHtml]="footerHtml"></app-footer>
Where the footerHtml
property in our component is defined as follows:
footerHtml = '<p>This is the footer with a <a href="/admin">link!</a></p>';
When the element is clicked, we check to make sure the user clicked on a hyperlink. If they did, we navigate using the router and prevent the default behavior. Here's a working StackBlitz example. Hope this helps!
href
? – Retentivity@Input
. How you go about it is up to you, but you should 100% definitely not be passing in pure HTML, especially if it comes from a user. – Retentivitytaggy
? – Sisyphus