【问题标题】:Angular4 routerLink inside innerHTML turned to lowercaseinnerHTML 中的 Angular4 routerLink 变为小写
【发布时间】:2017-06-18 08:22:47
【问题描述】:

我有一个从服务器获取页面内容的 cmd。然后内容可以包括 HTML 和链接。问题是当我显示这些数据时,链接不起作用。在查看页面源时,事实证明“routerLink”被转换为“路由器链接”,这就是它可能不起作用的原因。这是我的代码:

我的班级,请注意 routerLink 在这里是驼峰式

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

  constructor() { }

  ngOnInit() {}
}

还有我的html:

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

当我加载这个页面并查看源代码时 routerLink 现在是小写的

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

起初,我认为是 bypassSecurity 管道负责,但我检查了管道的输出,routerLink 仍然是驼峰式的。所以它似乎发生在其他地方。以防万一这也是我的 bypassSecurity 管道:

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

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

任何关于小写转换发生的位置和原因的建议将不胜感激:)

【问题讨论】:

  • 对不起,不明白你的意思,跟什么没区别?

标签: angular typescript


【解决方案1】:

jcdsr 的解决方案对我帮助很大。我通过将它与DomSanitizer 一起使用来完成这项工作。

我是这样做的:

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

};

组件

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

public html: SafeHtml;

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

模板

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

【讨论】:

  • 如果 URL 包含片段,则会出现问题。在这个原因中,您可能想要在 if (event.target.tagName === 'A') { 内执行类似 const hrefAtt = event.target.getAttribute('href'); if(hrefAtt.startsWith('/')) { let url; let fragment; if(hrefAtt.includes('#')) { url = hrefAtt.substr(0,hrefAtt.indexOf('#')); fragment = hrefAtt.substr(hrefAtt.indexOf('#') + 1); } else { url = hrefAtt; } this.router.navigate([url], { fragment: fragment }); event.preventDefault(); } 的操作
  • 非常感谢@Efe,这工作得很好。只是要注意私有 el:不需要 ElementRef 依赖。
  • 我们可以在这个实现中使用自定义的 safe-html 管道。 import { Pipe, PipeTransform } from '@angular/core'; import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; @Pipe({ name: 'safeHtml' }) export class SafeHtmlPipe implements PipeTransform { constructor(protected sanitizer: DomSanitizer) {} transform(value: any): SafeHtml { return this.sanitizer.bypassSecurityTrustHtml(value); } } 模板 -- &lt;span [innerHtml]="notification.message | safeHtml" appRouteTransfomer&gt;&lt;/span&gt;
  • 可爱的解决方案,它对我很有效。 (Angular 11.2.4注意:请遵循 Anguler Style 建议来选择指令名称Anguler directive nameing style link
【解决方案2】:

这是我的解决方案,你只需要使用html5属性。

在模板上:

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

在组件中:

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

或作为指令,

        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]);

            }


        }

在模板上作为指令:

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

缺点:

搜索引擎可以使用没有属性的“标签”。他们不会将其视为链接,也不会尝试将链接汁传递给它 - SEO。

【讨论】:

  • 您也可以根据需要使用管道,例如:
  • 非常好的解决方案,可以让链接正常工作而不会带来太多麻烦。谢谢!
  • @HostListener('click', ['$event.target']) onClick($event){ 为我工作,谢谢!
  • 要让 de SEO 工作,只需添加带链接的 href 属性,但在 getRoute(event) 方法中使用 event.preventDefault(); 禁用它们
【解决方案3】:

您可以使用以下简单方法在您的锚标记上添加路由

在.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'), "");

在 .html 中

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

在点击事件后的 .ts 中

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

它将在不重新加载整个页面的情况下路由视图

【讨论】:

    【解决方案4】:

    您是否尝试过其他 routerLink 语法以查看解释器的行为是否有所不同?

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

    代替你的

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

    【讨论】:

      【解决方案5】:

      我找到了一个非常方便的解决方案,可以使用 Angular Elements 在 innerHTML 中添加 routerLink

      1. 添加自定义元素 ng add @angular/elements
      2. 根据需要使用“href”的输入创建组件
      3. 在模板中这样使用:
      <a [routerLink]="href"><ng-content></ng-content></a>
      
      1. 在您想要在 innerHTML 中添加 routerLink 的首选组件内注册自定义元素
      2. 在innerHTML 字符串中使用您的自定义元素,而不是像这样的&lt;a&gt; 标记
      <your-custom-element href="/your/link">THE LINK TITLE</your-custom-element>
      

      这样您就可以完全控制路由器链接,并且仍然可以将 innerHTML 与来自外部(可信)来源的内容一起使用。

      【讨论】:

        【解决方案6】:

        我真的不知道你想在这里实现什么,但你不应该从后端获取整段代码。相反,只需接收值 'one' 并在客户端使用插值来生成 &lt;a routerLink="/one"&gt;ONE&lt;/a&gt;

        在模板中:

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

        【讨论】:

        • 它是一个 CMS。用户拥有所见即所得的编辑器,可以设计页面的整个部分,包括 html 和链接。
        • 这是 DOM 的默认行为。没有真正的解决方案,因为它总是会转换为小写。您可以做的是生成一个 (click)="method(value)" 然后在该方法中处理路由器导航,并将 value 参数作为目标路由。
        • 试试我上面的解决方案
        【解决方案7】:

        您应该从服务器返回&lt;a href="/one"&gt;ONE&lt;/a&gt; 而不是&lt;a routerLink="/one"&gt;ONE&lt;/a&gt;

        我已经尝试过了,这对我有用。

        【讨论】:

        • href 重新加载应用程序,我正在寻找一些解决方案,在标签中使用 routerLink 到 innerhtml
        • 你的解决方案不起作用,编译后的routerLink被渲染为带有“L”小写的'routerlink'
        猜你喜欢
        • 2018-01-26
        • 2020-04-29
        • 2020-10-20
        • 1970-01-01
        • 1970-01-01
        • 2022-12-10
        • 2019-10-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多