Add element with RouterLink dynamically

11,425

Solution 1

routerLink is a directive. Directives and Components are not created for HTML that is added using [innerHTML]. This HTML is not process by Angular in any way.

The recommended way is to not use [innerHTML] but DynamicComponentLoaderViewContainerRef.createComponent where you wrap the HTML in a component and add it dynamically.

For an example see Angular 2 dynamic tabs with user-click chosen components

Solution 2

routerLink cannot be added after the content is already rendered but you can still achieve the desired result:

  1. Create a href with dynamic data and give it a class:

    `<a class="routerlink" href="${someDynamicUrl}">${someDynamicValue}</a>`
    
  2. Add a HostListener to app.component that listens for the click and uses the router to navigate

    @HostListener('document:click', ['$event'])
    public handleClick(event: Event): void {
     if (event.target instanceof HTMLAnchorElement) {
       const element = event.target as HTMLAnchorElement;
       if (element.className === 'routerlink') {
         event.preventDefault();
         const route = element?.getAttribute('href');
         if (route) {
           this.router.navigate([`/${route}`]);
         }
       }
     }
    

    }

Share:
11,425
Jeroen1984
Author by

Jeroen1984

Updated on July 07, 2022

Comments

  • Jeroen1984
    Jeroen1984 almost 2 years

    When I put an anchor element in somewhere in an Angular component like this:

    <a [routerLink]="['/LoggedIn/Profile']">Static Link</a>
    

    everything is working fine. When clicking the link, the Angular router navigates to the target component.

    Now, I would like to add the same link dynamically. Somewhere in my app I have a "notification component", its single responsibility is to display notifications.

    The notification component does something like this:

    <div [innerHTML]="notification.content"></div>
    

    Where notification.content is a public string variable in the NotificationComponent class that contains the HTML to display.

    The notification.content variable can contain something like:

    <div>Click on this <a [routerLink]="['/LoggedIn/Profile']">Dynamic Link</a> please</div>
    

    Everything works fine and shows up on my screen, but nothing happens when I click the dynamic link.

    Is there a way to let the Angular router work with this dynamically added link?

    PS: I know about DynamicComponentLoader, but I really need a more unrestricted solution where I can send all kinds of HTML to my notification component, with all kind of different links.

    • ValeriiVasin
      ValeriiVasin over 6 years
      Hey, have you found the solution by any chance?
  • Jeroen1984
    Jeroen1984 about 8 years
    Hmm this was not the answer i was hoping for. I really do not want to create a component for every different notification. I was hoping there was a way to let angular scan the dom for any newly added directives or something...
  • Günter Zöchbauer
    Günter Zöchbauer about 8 years
    You can pass data to the component and bind to it in the components template to make reusable for similar scenarios. This limitation is usually only a problem if the HTML is provided by the user and it's impossible to know at build time.
  • Günter Zöchbauer
    Günter Zöchbauer about 8 years
    The component added dynamically can be provided by the other components, they don't need to be listed in directives: [...]
  • Günter Zöchbauer
    Günter Zöchbauer about 8 years
    Thanks :) See stackoverflow.com/questions/36325212/… for an example of such a wrapper.
  • Magani Felix
    Magani Felix about 7 years
    @GünterZöchbauer Thanks for the answer but the link you have provided does not work.
  • Günter Zöchbauer
    Günter Zöchbauer about 7 years
    DynamicComponentLoader is long gone. See the link in the comment. just before xours for more information.
  • NicBright
    NicBright over 3 years
    This is it! Your answer should be the accepted answer! Thank you very much!
  • AaronReynoldsUK
    AaronReynoldsUK about 3 years
    Much appreciated. This a really good work-around.
  • Matthew Hegarty
    Matthew Hegarty about 3 years
    You can use router.navigateByUrl() if you have multiple elements in your dynamic url.