Angular 7:div innerHTML绑定不适用于位置html数据的html清理或不进行html清理 [英] Angular 7: div innerHTML binding not working with or without html sanitization for location html data

查看:62
本文介绍了Angular 7:div innerHTML绑定不适用于位置html数据的html清理或不进行html清理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的数据源来自REST端点,它是html内容.一旦我获得了数据,我就尝试像这样将它们放入innerHTML中< div [innerHTML] ="mydata"></div> ,但是它不起作用.为了确保 mydata 有数据,我尝试使用像 {{mydata}} 这样的插值来打印 mydata ,并且效果很好.然后我四处搜寻,发现 mydata 需要进行清理,因为出于安全考虑,Angular不允许这样做.所以我创建了一个管道,使用 this.sanitizer.bypassSecurityTrustHtml(mydata),但即使在此之后它仍然无法正常工作.

Source for my data comes from a REST endpoint which is an html content. Once I got the data I tried to put in innerHTML like <div [innerHTML]="mydata"></div> but it did not work. Just to be sure mydata has data, I tried to print the mydata using interpolation like {{mydata}} and it works fine. I then searched around and found that mydata needs to be sanitised as Angular doesn't allows it due to security concerns. So I created a pipe in which I sanitized it using this.sanitizer.bypassSecurityTrustHtml(mydata) but even after this it's not working.

注意:我确实使用简单的HTML内容尝试了相同的代码,但效果很好. mydata 在有问题的情况下具有位置数据.

Note: I did try the same code with a simple HTML content and it worked fine. mydata in problematic case has location data.

要消毒的代码:

import { Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer, SafeHtml, SafeStyle, SafeScript, SafeUrl, 
SafeResourceUrl } from '@angular/platform-browser';

@Pipe({
   name: 'safe'
})
export class SafePipe implements PipeTransform {

constructor(protected sanitizer: DomSanitizer) {}

public transform(value: any, type: string): SafeHtml | SafeStyle | 
    SafeScript | SafeUrl | SafeResourceUrl {
    switch (type) {
        case 'html': return this.sanitizer.bypassSecurityTrustHtml(value);              
        case 'style': return this.sanitizer.bypassSecurityTrustStyle(value);
        case 'script': return this.sanitizer.bypassSecurityTrustScript(value);
        case 'url': return this.sanitizer.bypassSecurityTrustUrl(value);
        case 'resourceUrl': return this.sanitizer.bypassSecurityTrustResourceUrl(value);
        default: throw new Error(`Invalid safe type specified: ${type}`);
    }

然后我打电话给:< div [innerHTML] ="mydata | safe:'html'"></div>

根据@James Essex的回答我将代码修改为:

Based on the answers by @James Essex I modified the code to:

location.service.ts:从"rxjs"导入{Observable}

location.service.ts: import { Observable } from "rxjs"

 getData(): Observable <any> {
    return this.http.get(sourceUrl, { responseType: 'text'}).pipe(
      tap(value =>  {
        console.log(value);
     })
    );  
  }

component.ts`responseDataFromObservable:any;ngOnInit(){this.callLocationData();

component.ts `responseDataFromObservable: any; ngOnInit(){ this.callLocationData();

 callLocationData() {
this.locationService.getData().subscribe(response => {
  response = this.responseDataFromObservable;
     })
   }
 }

和html是:@ James Essex所说的正是

and html is: exactly what @ James Essex said.

但是仍然没有运气,UI显示空白屏幕,没有任何错误.

But still no luck, and UI is showing blank screen without any errors.

推荐答案

我认为您不应该尝试绕过安全性或将原始HTML注入< div [innerHTML] ="myData">.这似乎直接违反了用于跨视野脚本编写的Angular安全文档.

I do not think you should be trying to bypass security and or injecting raw HTML into a <div [innerHTML]="myData">. This seems to be in direct violation of the Angular security documents for cross-sight scripting.

模板层使用阴影DOM而不直接直接触摸HTML,并且可以通过 Renderer2 轻松访问.

The template layer uses a shadow DOM to not directly touch the HTML directly and it can be accessed easily by Renderer2.

我建议改用使用 Renderer2 ElementRef 的指令:

I would recommend developing a Directive instead which uses, Renderer2 and ElementRef:

import { Directive, Renderer2, ElementRef, OnInit, Input } from '@angular/core';

@Directive({
  selector: '[appSafeData]'
})
export class SafeDataDirective implements OnInit {
  @Input passedHtmlData;

  constructor(
    private renderer: Renderer2,
    private el: ElementRef,
) {}

  ngOnInit() {
    this.renderer.appendChild(this.el.nativeElement, passedHtmlData);
  }
}

对应服务:

  getData(): Observable<any> {
    this.http.get('putUrlHere');
  }

对应组件:

  let responseDataFromObservable; // Put whatever type it is string, interfaced typings or any?

  ngOnInit() {
    callLocationData();
  }

  callLocationData() {
    this.locationService.getData().subscribe(response => {
      response = this.responseDataFromObservable;
    }
  }

对应的HTML:

<ng-container *ngIf="responseDataFromObservable">
  <div appSafeData [passedHtmlData]="responseDataFromObservable" id="my-data-wrapper">
    <!-- Your API data as HTML will be added here -->
  </div>
</ng-container>

注意:我相信使用< ng-container> 设置模板可能会有更好的效果,但是类似这样的方法是在不影响安全性的前提下注入数据的更好方法.

NOTE: I am sure there might be a better of setting up the Template using <ng-container> but something like this is a much better way to injecting the data with out compromising security.

可能有帮助的其他链接:

Additional Links that might help:

  1. Alligator.io-使用Renderer2
  2. Alligator.io-使用ng-container
  3. Angular.io-Renderer2文档

这篇关于Angular 7:div innerHTML绑定不适用于位置html数据的html清理或不进行html清理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆