Skip to content Skip to sidebar Skip to footer

Can't Render Routerlink In Innerhtml In Angular

In the component code I have a field called taggy containing a full anchor tag. At first, in my HTML, I rendered it to the screen, which, of course didn't work out because I only s

Solution 1:

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);
  returntrue;
}

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>'
})
exportclassFooterComponent {
  @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.targetinstanceofHTMLAnchorElement === false) { 
      return;
    }
    // Prevent page from reloading
    event.preventDefault();
    let target = <HTMLAnchorElement>event.target;
    // Navigate to the path in the linkthis.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!

Solution 2:

Based on the question, #Dean solution works fine however, it does not work for external link. That is, it can only work for angular route path. Below is my solution to solve both internal and external url/link.

import { Component, Input, HostListener } from'@angular/core';
  import { Router } from'@angular/router';

  import { Component, Input, HostListener } from'@angular/core';
  import { Router } from'@angular/router';

  @Component({
    selector: 'app-footer',
    template: '<div [innerHTML]="footerHtml"></div>'
  })
  exportclassFooterComponent {
    footerHtml = '<p>This is the innerHTML content with angular valid path  <a href="/admin">internal link!</a> and external link <a target="_blank" href="https://google.com">external link</a></p>';

    // Watch for clicks in our component@HostListener('click', ['$event'])
    onClick(event: MouseEvent) {
    this.routingService.urlLocator(event);
    // Do nothing if no anchor tag.if (event.targetinstanceofHTMLAnchorElement === false) {
      return;
    }

    // Prevent normal html anchor behaviour
    event.preventDefault();

    // Checks if the anchor has a full url name or if target is "_blank"// That is, target external urlif (event.target.target === '_blank') {
      // open it in new window (You can decide to use window.location.href)window.open(event.target.href); 
    } else {
      // handle valid angular route pathconst target = <HTMLAnchorElement>event.target;
      this.router.navigate([target.pathname]);
    }
  }
}

Solution 3:

If you don't mind installing a library for this, have a look at ngx-dynamic-hooks. It can replace any piece of text in a dynamic string of content with an actual Angular component - including link-elements.

Funnily enough, I've written an example based on the exact idea of automatically replacing internal links with [RouterLinks]. Have a look at it here (or in this Stackblitz).

Post a Comment for "Can't Render Routerlink In Innerhtml In Angular"