【问题标题】:How to Allow Unsafe HTML in angular 5如何在 Angular 5 中允许不安全的 HTML
【发布时间】:2021-02-09 20:42:13
【问题描述】:

您好,我正在为我的 Web 应用程序使用 Angular 5。我的用例是从 Java 服务返回一些动态创建的 html 内容,并在 Angular 组件中使用相同的内容。我能够通过 DomSanitizer 绕过角度安全性,但点击事件仍然无法正常工作。

下面是我的代码。

import { Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import DOMPurify from 'dompurify';
declare var angular: any;

@Pipe({
    name: 'safeHtml'
})
export class SafeHtmlPipe implements PipeTransform {

    constructor(protected sanitizer: DomSanitizer) {}

    public transform(value: any): any {
        const sanitizedContent = DOMPurify.sanitize(value);
        console.log(sanitizedContent);
        return this.sanitizer.bypassSecurityTrustHtml(sanitizedContent);

    }
}

这是你用来绕过不受信任的 html 的有角度的 safeHtml 管道。

Component.ts - 用于服务调用

import { Component, OnInit } from '@angular/core';
import {ViewReviewService} from '../../services/view-review-service';
import {Response} from '@angular/http';

@Component({
  selector: 'app-sample-hit',
  templateUrl: './sample-hit.component.html',
  styleUrls: ['./sample-hit.component.css']
})
export class SampleHitComponent implements OnInit {
  sampleData: any;
  
  constructor(private viewReviewService: ViewReviewService) { }

  ngOnInit() {
    
    this.hitSample();
  }

  hitSample() {
    this.viewReviewService.hitSample().subscribe((res: Response) =>  {
      console.log(res['_body']);
      this.sampleData =  res['_body'];
    });
  }

  
  callSampleFunction(value: string) {
    console.log('hit hit ' + value);
  }
}

This.sampleData = '<a> This is my a tag</a>
                  <a (click)="callSampleFunction(value1)"> This tag will call function</a>
                  <a (click)="callSampleFunction(value2)"> This tag will call same function with 
                  different value</a>
                  <p> other html </a>'

component.html

<div [innerHTML]="sampleData | safeHtml" >
</div>

我还需要做什么。请帮忙?

【问题讨论】:

    标签: angular


    【解决方案1】:

    注入的 html 不会被“棱角化”,因此像 (click) 这样的绑定将不起作用。

    您必须使用纯 JavaScript,例如 "onClick"="someJsFunction"。然后我不知道如何从 JS 代码调用组件代码(你必须能够做到这一点,例如从浏览器控制台)。

    一个讨厌的解决方法是通过设置全局变量来公开组件实例。

    【讨论】:

    • 遵循您的建议。我在同一个示例组件中创建了一个 Javascript 文件。添加了函数 callSampleFunction() { alert('i am a javascript function');但是现在当我从浏览器中单击时,我面临的功能不是未定义的。任何建议请。
    • 你是否在某处包含了你的 js 文件?正如我所写,您必须能够在全局范围(或​​任何其他定义的范围)中调用该函数,因此它也必须在浏览器控制台中工作。如果您从浏览器控制台调用 callSampleFunction 是否有效?我猜不会。 JS 文件必须通过 DOM 导入或通过 angular.js 中的脚本部分打包到您的应用程序中
    • 是的,我无法从浏览器调用它。
    • 我在 index.html 中包含了 JS 文件 - 现在这个 JS 文件应该有全局范围?
    • 这个路径对于 ng serve 是无效的。请将该脚本添加到 angular.json stackoverflow.com/a/44817439/1527544 的脚本部分
    【解决方案2】:

    您不能通过添加 (click) 来制作可点击元素,因为它是一个角度事件,不会在 [innerHTML] 内编译。但是,有一种类似于您的简单方法如下:

    1- 从后端或管道中为您的 HTML 元素添加一个唯一的类,如下所示:

    public transform(value: any): any {
        const sanitizedContent = DOMPurify.sanitize(value);
        console.log(sanitizedContent);
        return this.sanitizer.bypassSecurityTrustHtml(this.modify(sanitizedContent));
    
    }
    
    modify(text: string){
     // add class here to your text and return it
    
    }
    

    假设你的类名是 someClass

    This.sampleData = '<a class="someClass"> This is my a tag</a>
                      <a (click)="callSampleFunction(value1)"> This tag will call function</a>
                      <a (click)="callSampleFunction(value2)"> This tag will call same function with 
                      different value</a>
                      <p> other html </a>'
    

    2-在你的component.ts文件中视图初始化事件之后你可以添加如下代码:

      ngAfterViewInit() {
        // assume dynamic HTML was added before
        const elementList = this.elRef.nativeElement.querySelectorAll('.someClass');
        if (elementList) {
            for (const element of elementList) {
            element.addEventListener('click', this.callSampleFunction.bind(this));
             // bind an event listener to every element with the class someClass
          }
    
        } 
      }
    

    【讨论】:

    • 那是不可行的。因为在最坏的情况下会有数以万计的元素。我要解决的问题是在 java 中计算并创建 HTML 而不是 Javascript。
    • 有一些管道可以触发整个文档,例如我曾经用于整个文档的链接管道,这是可行的。检查stackblitz.com/edit/linkify-pipe
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-22
    • 2023-02-08
    • 2011-04-16
    • 2017-02-12
    • 2021-07-30
    • 2018-07-16
    相关资源
    最近更新 更多