Reputation: 91
I am using Angular 6. I just want to create a dynamic route by using the innerHTML
. I tried the following code but it is not working.
In the component file, I wrote the following code inside the constructor:
this.anchor = "<a routerLink='login'>Dynamic Login</a>"
In the template file, I wrote the following code:
<div [innerHtml]="anchor"></div>
Upvotes: 7
Views: 8216
Reputation: 109
My decision for subj with innerHtml, i18n translate and routerLink below: component html:
<p
(click)="routerlinkClicked($event)"
[innerHTML]="signupSuccessText"
></p>
component.ts:
public signupSuccessText: SafeHtml = this.sanitizer.bypassSecurityTrustHtml(this.translate.instant('signup.successReport.body.text'))
constructor(
private sanitizer: DomSanitizer,
private router: Router,
public translate: TranslateService
) { }
public routerlinkClicked(event: Event): void {
const target: HTMLElement = event.target as HTMLElement;
const attributes: NamedNodeMap = target.attributes;
const redirectUrl: string = attributes && attributes['routerlink'] ? attributes['routerlink'].value : '';
if (redirectUrl) {
this.router.navigate([redirectUrl]);
}
}
finally translate i18n en.json:
"signup.successReport.body.text": "You have almost finished. <br /> Please, check your email and follow <br /> the verification link to complete you registration.<br /><br /> After you finish, come back and <a routerLink='/login' class='reset__link' data-test-id='loginLink'>log in</a>.",
cheers!
Upvotes: 1
Reputation: 11
I got the same problem, but I solved it.
@Directive({
selector: "[linkify]",
})
// * Apply Angular Routing behavior, PreventDefault behavior
export class CustomLinkDirective {
@Input()
appStyle: boolean = true;
constructor(
private router: Router,
private ref: ElementRef,
@Inject(PLATFORM_ID) private platformId: Object
) {}
@HostListener("click", ["$event"])
onClick(e: any) {
e.preventDefault();
const href = e.target.getAttribute("href");
href && this.router.navigate([href]);
}
ngAfterViewInit() {
if (isPlatformBrowser(this.platformId)) {
this.ref.nativeElement.querySelectorAll("a").forEach((a: HTMLElement) => {
const href = a.getAttribute("href");
href &&
this.appStyle &&
a.classList.add("text-indigo-600", "hover:text-indigo-500");
});
}
}
}
use it
<p linkify
class="mt-3 text-lg text-gray-500 include-link"
[innerHtml]="apiSectionText"
></p>
Upvotes: 0
Reputation: 1920
@Alex Chebotarsky solution is good and prooves the concept.
I can show you how I've used it as a pipe for long description where you encounter more links.
docs.pipe.ts
@Pipe({ name: 'docs' })
export class DocsPipe implements PipeTransform {
constructor(private sanitizer: DomSanitizer) {}
transform(value: string, item: IStack): SafeHtml {
value = value.replace(DocsKeywords.language, `<a class="doc-type" [routerLink]="/tabs/search,${item.area[0]},${item.id}">${DocsKeywords.language}</a>`);
value = value.replace(DocsKeywords.frontend, `<a class="doc-type" [routerLink]="/tabs/search,${item.area[0]},${item.id}">${DocsKeywords.frontend}</a>`);
value = value.replace(DocsKeywords.framework, `<a class="doc-type" [routerLink]="/tabs/search,${item.area[0]},${item.id}">${DocsKeywords.framework}</a>`);
return this.sanitizer.bypassSecurityTrustHtml(value);
}
}
Afterwards my rendered HTML & DOM looks like this:
some-component.html
<p class="description" [innerHtml]="item.longDescription | docs: item">
some-component.ts
@HostListener('click', ['$event'])
onClick(e) {
if (e.target.classList.contains("doc-type")) {
const urlSegments = e.target.getAttribute('[routerlink]').split(',');
this.router.navigate(urlSegments);
};
}
Upvotes: 0
Reputation: 513
There is one hacky solution that I used when encountered same problem as you did since I didn't find anything better. In template I had span
where I was setting innerHtml
that html was coming from server and it could have a
tag as well as any other formatting html tags. So the solution is to add click event:
<span [innerHtml]="customHtml" (click)="processLinks($event)"></span>
And in our ts file process them:
customHtml: string = 'Hey <a href="/help/">this is</a> a link';
// Don't forget to import and inject the router
constructor(private router: Router) {}
// ...
processLinks(e) {
const element: HTMLElement = e.target;
if (element.nodeName === 'A') {
e.preventDefault();
const link = element.getAttribute('href');
this.router.navigate([link]);
}
}
Notice that you can do anything with the link here, if you need you can add some conditions or transform links before navigating to them.
Hope it helps. I know it's not the best solution, there must be something better. But that's what I came up with in a rush.
Upvotes: 16
Reputation: 1453
this.anchor = "<a routerLink='login'>Dynamic Login</a>"
<div [innerHtml]="anchor"></div>
Above codes won't cause Angular to process anything Angular-specific in anchor
.
Angular replaces Angular specific markup at build time with generated code. Markup added at runtime won't be processed by Angular.
To add HTML that contains Angular-specific markup (property or value binding, components, directives, pipes, ...) it is required to add the dynamic module and compile components at runtime. This answer provides more details How can I use/create a dynamic template to compile dynamic Component with Angular 2.0?
Upvotes: 2
Reputation: 620
I had the same issue. I just replaced the <a routerLink="/something">Something</a>
to
<a href="#/something">Something</a>
And it works just fine
Upvotes: -2