Converting Angular 4 RouterLink within InnerHTML to lowercase

I am facing an issue with a command I have, where I retrieve content from the server that includes HTML and links. The problem arises when displaying this data as the links do not work. Upon inspecting the page source, I noticed that "routerLink" is being transformed into "router link," which may be why it's not functioning correctly. Below is the code snippet:

Here is my class, noting that routerLink is in camelcase here:

export class TwoComponent implements OnInit {
  data = '<a routerLink="/one">ONE</a>'; //this will actually come from backend server

  constructor() { }

  ngOnInit() {}
}

And my html:

<div [innerHTML]="data | bypassSecurity"></div>

Upon loading the page and viewing the source, the routerLink has now been converted to lowercase:

<a routerlink="/one">ONE</a>

Initially, I suspected the bypassSecurity pipe to be responsible but after checking its output, I observed that routerLink was still in camel case. It appears that the transformation happens elsewhere. Here is my bypassSecurity pipe for reference:

export class BypassSecurityPipe implements PipeTransform {
  constructor(private sanitized: DomSanitizer) {}

  transform(value): any {
    return this.sanitized.bypassSecurityTrustHtml(value);
  }
}

If you have any insights on why and where this lowercase transformation occurs, your advice would be greatly appreciated :)

Answer №1

After consulting jcdsr's solution, I was able to make significant progress with my project. By incorporating DomSanitizer, everything fell into place.

Here is the step-by-step process I followed:

RouteTransformerDirective

import { Directive, ElementRef, HostListener } from '@angular/core';
import { Router } from '@angular/router';

@Directive({
  selector: '[routeTransformer]'
})
export class RouteTransformerDirective {

  constructor(private el: ElementRef, private router: Router) { }

  @HostListener('click', ['$event'])
  public onClick(event) {
    if (event.target.tagName === 'A') {
      this.router.navigate([event.target.getAttribute('href')]);
      event.preventDefault();
    } else {
      return;
    }
  }

};

Component

import { DomSanitizer, SafeHtml } from '@angular/platform-browser';

public html: SafeHtml;

constructor(private sanitizer: DomSanitizer) {
    this.html = sanitizer.bypassSecurityTrustHtml('<a href="/something">Link</a>');
}

Template

<div [innerHtml]="html" routeTransformer></div>

Answer №2

Here is a simple solution using only html5 attributes.

Within the template:

<div [innerHtml]="testHtml" (click)="getRoute($event)"></div>

In the component:

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

@Component({
  selector: 'app',
  templateUrl: './app.component.html',
  styleUrls:['./app.component.css'],
})

export class oneComponent implements OnInit {

    testHtml: any;

    constructor( private router: Router,) {}

    this.testHtml=`
    <br>
    ------- <span data-link="/page 1">Page 1</span> ------- 
    <br>
    ------- <a data-link="/page 2">Page 2</a> ------- 
    <br>
    text -- `;


    getRoute(event) {
        var goRoute = event.target.getAttribute('data-link')
        alert(goRoute);
        this.router.navigate([goRoute]);
    }
}

Alternatively, as a directive:

import { Directive, ElementRef, HostListener } from '@angular/core';
import { Router } from '@angular/router';

@Directive({     
    selector: '[routeDirective]'
})

export class routeDirective {

  constructor(private el: ElementRef, private router: Router) { }

    @HostListener('click', ['$event.target']) onClick($event){
        console.info('clicked: ' + $event.getAttribute('data-link'));
        var goRoute = $event.getAttribute('data-link');
        this.router.navigate([goRoute]);

    }
}

Using the directive in the template:

<div [innerHtml]="testHtml" routeDirective></div>

Drawbacks:

It's worth noting that search engines may not recognize "a tags" without attributes as links, affecting SEO performance.

Answer №3

Here's a simple solution for adding routes to anchor tags:

In your TypeScript file (.ts)

let baseUrl = 'http://localhost/'
let body = `<a href="http://localhost/discussion/details/">route detail</a> and 2nd <a href="http://localhost/discussion/list">route list</a>`
body = body.replace(/href/g, "value");
body = body.replace(new RegExp(baseUrl, 'g'), "");

In your HTML file (.html)

<div (click)='changeRoute($event)' [innerHTML]="body"></div>

In your TypeScript file after the click event

changeRoute(value){
  let myRoute=value.target.attributes.value.value;
  this.router.navigate([myRoute]);
 }

This method will navigate without refreshing the entire page.

Answer №4

Have you experimented with alternative routerLink syntax to observe any variations in behavior?

<a [routerLink]="javascript code that produces a string or an array"> </a>

rather than using

<a routerlink="/one">ONE</a>

Answer №5

I came across a clever solution for incorporating the routerLink attribute within the innerHTML in Angular Elements:

  1. Install Custom Elements ng add @angular/elements
  2. Create Component as desired with an input for "href"
  3. Utilize it in the template like so:
<a [routerLink]="href"><ng-content></ng-content></a>
  1. Declare Custom Element within the chosen Component where you intend to include the routerLink in the innerHTML
  2. In the innerHTML string, replace the <a> tag with your custom element like this
<your-custom-element href="/your/link">THE LINK TITLE</your-custom-element>

This method provides full control over the router link while still using innerHTML with content sourced externally (and considered trustworthy).

Answer №6

I'm not exactly sure what your goal is here, but it's recommended not to fetch the entire code snippet from the backend. Instead, simply retrieve the value 'one' and utilize interpolation on the client side to create

<a routerLink="/one">ONE</a>
:

Within the template:

<a routerLink="value">{{value}}</a>

Answer №7

It is recommended to send back

<a href="/one">ONE</a>
rather than
<a routerLink="/one">ONE</a>
from the server.

I tested this approach and confirmed its effectiveness.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Incorporating information into Observable in Angular 2

I'm currently working on loading gifs from the API based on a search parameter in batches of 20. Once I reach the bottom of the page, I need to load another 20. To achieve this, I've implemented observables. However, I'm facing an issue with ...

Getting a 404 error despite the status code being properly set to 200 in the response

I have developed a NodeJS Express API using TypeScript. All API calls are returned through the following method: private setResponseWithStatusCode<TResult>( result: TResult, httpStatusCode: number, response: Response): Response { l ...

Is it true that NativeScript with Angular2's UI does not provide mobile client support?

Currently I am delving into the world of developing cross-platform mobile-client apps with Nativescript. To my surprise, the UI component options in Nativescript are quite limited and whenever I refer to the official documentation, it often redirects me to ...

How does the use of nodejs, a server-side scripting language, tie into ReactJs or other front-end languages?

Can Node, being a server-side scripting language, be effectively utilized in the development of front-end applications such as npx create-react-app or npx create-nuxt-app? ...

Is it necessary to unsubscribe from multiple switchmaps?

Consider the following scenario: Should I implement an unsubscribe in each instance of switchMap? And is it necessary to include a takeUntil after every switchMap operation? this.sharedSrv.postDetail.pipe( switchMap(post => { if (post) { th ...

Challenges in transmitting values from Angular to NodeJS

I'm currently working on a user-friendly website using Angular and nodeJS. I'm attempting to pass a single parameter "email" from an Angular service when accessing a route in the node server. Here is the function in the Angular service: https:// ...

Is it possible to eliminate auxiliary routes in Angular 4?

Recently, I came across an interesting scenario with two <router-outlet> tags, one with a name property. To test this, I set up the following router mapping: export const routing = [ {path:'', pathMatch:'full', component:E ...

Angular: efficient exchange of information among components

I have a component X that handles a WebSocket. And within component X, I also have multiple presentation components (e.g. Y). Whenever the WebSocket receives a specific message, I need to perform an action in a particular component (e.g. refresh data). To ...

Stop allowing the entry of zero after a minus sign

One of the features on our platform allows users to input a number that will be automatically converted to have a negative sign. However, we want to ensure that users are unable to manually add a negative sign themselves. We need to find a solution to pre ...

What sets apart a class from a service in NativeScript?

I am embarking on the journey of learning Nativescript + Angular2, and while reading through the tutorial, I came across this interesting snippet: We’ll build this functionality as an Angular service, which is Angular’s mechanism for reusable classes ...

Mastering the utilization of custom input events in PrimeNG with Angular

I am currently working on an Angular 16 project. Within this project, I have implemented a number input field that is being validated using formControls. To make my work more efficient, especially since this input is used frequently, I decided to encapsula ...

The CORS policy has blocked access to 'http://localhost:8080/BeginSignup' from 'http://localhost:4200'

I'm having trouble with a CORS policy error when sending a fetch POST request to my Golang AppEngine API. Although I don't understand why this error is occurring. Below is the code I'm using: Below is the Angular code calling the API: priva ...

What is the best way to transform this Ajax query into an HTTP client request in Angular 8?

I have an ajax request that looks like this: var data = { REQUEST: 'GetFeatureInfo', SERVICE: 'WMS', VERSION: '1.1.1', LAYERS: layerName, STYLES: '', FORMAT: 'image/png', INFO ...

Trouble with storing data in Angular Reactive Form

During my work on a project involving reactive forms, I encountered an issue with form submission. I had implemented a 'Submit' button that should submit the form upon clicking. Additionally, there was an anchor tag that, when clicked, added new ...

"Encountered an issue while attempting to access the 'visit' property of an undefined entity

Out of nowhere, Angular is displaying an error during compilation at the initial stage and then the entire screen goes blank. I'm puzzled as to why? Uncaught TypeError: Cannot read property 'visit' of undefined at convertPropertyBinding ...

The clash between a static property name type and a dynamic property name on an interface is causing

My interface, Item, is quite straightforward and is applied to various objects. This interface mandates that each of these objects must have an assigned itemName property, but they can also include additional properties with dynamic names if necessary. T ...

Transform a string with delimiter into a JSON object containing key-value pairs extracted from the string

Looking to transform a string into an object in typescript for NodeJS API var string = "1234|Tom|NYC|Student|Active" The goal is to map the string to: { "Id": 1234, "Name": "Tom", "City": "NYC ...

What is the best way to incorporate master/detail components without relying on hierarchical routes?

I need to combine the following elements. An index page with the route /items (plural). This page should be scrollable. When clicking on individual items, I want to display a detail page with the route /item/:id (singular). The detail page should have a ...

How to effectively handle null values using try..catch statement in typescript

As a beginner, I am learning how to write a try/catch statement in TypeScript. My issue is that there is a function within the "try" block that returns null. How can I implement code in the "catch" block specifically for when the function in "try" returns ...

Error: The method map is not a valid function for the HTTP GET operation

In my Angular 4 project, I'm attempting to retrieve data from an API. Following the instructions in this article which outlines the process, but I encountered an error: TypeError: this.http.get(...).map is not a function This is the code snippet I ...