การเชื่อม HTML เชิงมุม


840

ฉันกำลังเขียนแอปพลิเคชันเชิงมุมและฉันมีการตอบสนอง HTML ที่ฉันต้องการแสดง

ฉันจะทำอย่างไร ถ้าฉันเพียงใช้ไวยากรณ์การผูกพัน{{myVal}}มันเข้ารหัสอักขระ HTML ทั้งหมด (แน่นอน)

ฉันต้องการอย่างใดอย่างหนึ่งที่จะผูกinnerHTMLของdivกับค่าตัวแปร


โพสต์ที่เกี่ยวข้องสำหรับการกำหนด CSS ในส่วนประกอบเพื่อให้ทำงานได้อย่างถูกต้องใน HTML binding stackoverflow.com/questions/36265026/ …
y3sh

1
ฉันรวบรวมวิดีโอตอบกลับเพื่ออธิบายวิธีแก้ปัญหาและยกตัวอย่าง: youtube.com/watch?v=Pem2UXp7TXA
Caleb Grams

จะเกิดอะไรขึ้นถ้าตัวแปรมีแท็กเชิงมุมหรือแท็กที่ผู้ใช้กำหนดเช่น <span [routerLink] = ['some-router']> ลิงก์ </span>
G. Muqtada

คำตอบ:


1337

ไวยากรณ์ที่ถูกต้องมีดังต่อไปนี้:

<div [innerHTML]="theHtmlString"></div>

เอกสารอ้างอิง


4
สิ่งนี้มีประโยชน์: victorsavkin.com/post/119943127151/angular-2-template-syntax
malix

14
มีวิธีใดบ้างที่ฉันสามารถบังคับให้เชิงมุมเรียกใช้การโยงกับองค์ประกอบของ InnerHTML นั้น ฉันต้องใช้ <a [router-link เหมือน="..."> </a> และต้องการระบุสิ่งนั้นจาก html ภายนอก
yeliha

4
@thouliha ฉันขอแนะนำให้เริ่มโพสต์ใหม่เกี่ยวกับคำถามของคุณ
prolink007

4
มันแสดงผลสตริงในกรณีของฉัน แต่ทำบางสิ่งบางอย่างเพื่อมาร์กอัป ดูเหมือนว่าจะมีการลอกออกคุณลักษณะในมาร์กอัป ฉันอยู่ที่ 2.4.6
paqogomez

2
@paqogomez ใช่มันแยกแยะสิ่งที่เห็นว่าไม่ปลอดภัย
Juan Mendes

312

Angular 2.0.0 และ Angular 4.0.0 สุดท้าย

สำหรับเนื้อหาที่ปลอดภัยเพียง

<div [innerHTML]="myVal"></div>

DOMSanitizer

HTML ที่ไม่ปลอดภัยที่อาจเกิดขึ้นจะต้องมีการทำเครื่องหมายอย่างชัดเจนว่าเชื่อถือได้โดยใช้ Angulars DOM sanitizer ดังนั้นไม่ได้ตัดส่วนที่ไม่ปลอดภัยของเนื้อหา

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

ด้วยท่อเหมือน

@Pipe({name: 'safeHtml'})
export class Safe {
  constructor(private sanitizer:DomSanitizer){}

  transform(style) {
    return this.sanitizer.bypassSecurityTrustHtml(style);
    //return this.sanitizer.bypassSecurityTrustStyle(style);
    // return this.sanitizer.bypassSecurityTrustXxx(style); - see docs
  }
}

ดูเพิ่มเติมใน RC.1 บางสไตล์ไม่สามารถเพิ่มได้โดยใช้ไวยากรณ์การเชื่อมโยง

และเอกสาร: https://angular.io/api/platform-browser/DomSanitizer

คำเตือนความปลอดภัย

ผู้ใช้ที่เชื่อมั่นที่เพิ่ม HTML อาจมีความเสี่ยงด้านความปลอดภัย เรื่องก่อนสถานะเอกสาร :

การเรียกbypassSecurityTrust...API ใด ๆจะปิดใช้งานการฆ่าเชื้อในตัวของ Angular สำหรับค่าที่ส่งเข้าตรวจสอบและตรวจสอบค่าและเส้นทางรหัสทั้งหมดอย่างรอบคอบเพื่อเข้าสู่การโทรนี้ ตรวจสอบให้แน่ใจว่ามีการหลีกเลี่ยงข้อมูลผู้ใช้อย่างเหมาะสมสำหรับบริบทความปลอดภัยนี้ สำหรับรายละเอียดเพิ่มเติมให้ดูที่คู่มือการรักษาความปลอดภัย

มาร์กอัปเชิงมุม

สิ่งที่ต้องการ

class FooComponent {
  bar = 'bar';
  foo = `<div>{{bar}}</div>
    <my-comp></my-comp>
    <input [(ngModel)]="bar">`;

กับ

<div [innerHTML]="foo"></div>

fooจะไม่ทำให้เกิดเชิงมุมกับกระบวนการอะไรเชิงมุมเฉพาะ Angular แทนที่มาร์กอัพเฉพาะ Angular ณ เวลาบิลด์ด้วยโค้ดที่สร้างขึ้น เพิ่มมาร์กอัปเมื่อรันไทม์จะไม่ได้รับการประมวลผลโดยเชิงมุม

ในการเพิ่ม HTML ที่มีมาร์กอัปเฉพาะเชิงมุม (การผูกคุณสมบัติหรือค่าส่วนประกอบคำสั่งไพพ์ ... ) จำเป็นต้องเพิ่มโมดูลแบบไดนามิกและส่วนประกอบคอมไพล์ที่รันไทม์ คำตอบนี้ให้รายละเอียดเพิ่มเติมฉันจะใช้ / สร้างแม่แบบไดนามิกเพื่อรวบรวมส่วนประกอบแบบไดนามิกด้วย Angular 2.0 ได้อย่างไร?


13
นี่ควรเป็นคำตอบ ให้ความสนใจกับสองบรรทัดที่ใส่ความคิดเห็นไว้ เป็นอันที่สองที่จัดการกับ HTML
paqogomez

8
อย่าลืมimport { BrowserModule, DomSanitizer } from '@angular/platform-browser'
paqogomez

4
นอกจากนี้import { Pipe } from '@angular/core'
Appulus

1
นี่คือคำตอบได้ที่นี่! กำลังค้นหารายละเอียดเกี่ยวกับสิ่งที่อยู่ใน NG2 แทนที่ $ SCE ของ NG1 ;)
jrista

2
คำตอบที่ดี แก้ไขปัญหาของฉัน ขอบคุณมาก. ในกรณีที่มีคนไม่แน่ใจว่าจะใช้ไพพ์ในองค์ประกอบ (เช่นเดียวกับฉัน): angular.io/guide/pipesเพียงเพิ่มไปยังการประกาศของคุณในโมดูลที่สอดคล้องกันและvoilá!
Alejandro Nagy

169

[innerHtml] เป็นตัวเลือกที่ดีในกรณีส่วนใหญ่ แต่มันล้มเหลวด้วยสตริงที่มีขนาดใหญ่มากหรือเมื่อคุณต้องการสไตล์ที่กำหนดโค้ดยากใน html

ฉันต้องการแบ่งปันวิธีการอื่น:

สิ่งที่คุณต้องทำคือสร้าง div ในไฟล์ html ของคุณและตั้งรหัส:

<div #dataContainer></div>

จากนั้นในองค์ประกอบ Angular 2 ของคุณสร้างการอ้างอิงถึงวัตถุนี้ (TypeScript ที่นี่):

import { Component, ViewChild, ElementRef } from '@angular/core';

@Component({
    templateUrl: "some html file"
})
export class MainPageComponent {

    @ViewChild('dataContainer') dataContainer: ElementRef;

    loadData(data) {
        this.dataContainer.nativeElement.innerHTML = data;
    }
}

จากนั้นก็ใช้ loadDataฟังก์ชั่นเพื่อต่อท้ายข้อความบางส่วนเพื่อองค์ประกอบ HTML

มันเป็นวิธีที่คุณจะทำได้โดยใช้จาวาสคริปต์ แต่ในสภาพแวดล้อมเชิงมุม ฉันไม่แนะนำเพราะทำให้รหัสยุ่งมากขึ้น แต่บางครั้งก็ไม่มีตัวเลือกอื่น

ดูเพิ่มเติมAngular 2 - innerHTML ใส่สไตล์


1
ฉันไม่เห็นความแตกต่างกับโซลูชันอื่นยกเว้นว่าคุณเข้าถึงคุณสมบัติของnativeElementโดยตรงซึ่งถือว่าเป็นการปฏิบัติที่ไม่ดี ฉันแน่ใจว่า[innerHTML]="..."ทำเช่นเดียวกันภายใต้ประทุน แต่ในทางปฏิบัติ Angular2 ที่ดี
GünterZöchbauer

1
นั่นไม่ใช่วิธีการทำงานของ Angular2 HTML ที่คุณเพิ่มไปยังเทมเพลตของส่วนประกอบ Angular2 นั้นได้รับการประมวลผลครั้งแรกโดย Angular และหลังจากนั้นจะถูกเพิ่มลงใน DOM เท่านั้น คุณเคยเจอปัญหาเกี่ยวกับ[innerHTML]และสตริงจำนวนมากใน Angular2 หรือไม่?
GünterZöchbauer

1
ฉันคิดว่าสิ่งนี้ควรรายงานว่าเป็นข้อบกพร่อง ขอบคุณสำหรับการโพสต์ผลลัพธ์ของคุณ
GünterZöchbauer

25
[innerHtml]ลบการกำหนดสไตล์ฮาร์ดโค้ดใน Html เพื่อรวมโปรแกรมแก้ไขแบบ wysiwyg ฉันต้องใช้วิธีการที่ระบุไว้ที่นี่
Jony Adamit

2
สำหรับฉันโซลูชันนี้ทำงานเพื่อรวมเอกสาร SVG แบบอินไลน์ในขณะที่[innerHTML]วิธีการไม่ได้
Jared Phelps

54

ใน angular2@2.0.0-alpha.44:

Html-Binding จะไม่ทำงานเมื่อใช้{{interpolation}}และใช้ "Expression" แทน:

โมฆะ

<p [innerHTML]="{{item.anleser}}"></p>

-> ส่งข้อผิดพลาด (การแก้ไขแทนนิพจน์ที่คาดหมาย)

แก้ไข

<p [innerHTML]="item.anleser"></p>

-> นี่เป็นวิธีที่ถูกต้อง

คุณอาจเพิ่มองค์ประกอบเพิ่มเติมในการแสดงออกเช่น:

<p [innerHTML]="'<b>'+item.anleser+'</b>'"></p>

เปรย

HTML ที่เพิ่มโดยใช้[innerHTML](หรือเพิ่มแบบไดนามิกโดยวิธีอื่นเช่นelement.appenChild()หรือคล้ายกัน) จะไม่ถูกประมวลผลโดย Angular ในทางใด ๆ ยกเว้นการฆ่าเชื้อเพื่อวัตถุประสงค์ด้านความปลอดภัย
สิ่งต่าง ๆ เหล่านี้ทำงานได้เฉพาะเมื่อ HTML ถูกเพิ่มแบบคงที่ให้กับเทมเพลตส่วนประกอบ หากคุณต้องการสิ่งนี้คุณสามารถสร้างส่วนประกอบที่รันไทม์อย่างที่อธิบายไว้ในฉันจะใช้ / สร้างแม่แบบไดนามิกเพื่อรวบรวมส่วนประกอบแบบไดนามิกด้วย Angular 2.0 ได้อย่างไร


1
แก้ไขหลังจากลองใหม่อีกครั้ง พบโซลูชัน :)
jvoigt

3
ตัวอย่างที่สามไม่ทำงาน การแสดงออกไม่ได้ประเมิน ผลลัพธ์เป็นเพียงสตริง ... วิธีอื่นในการรวมความน่าเชื่อถือ HTML กับองค์ประกอบแท็กอื่น ๆ
Kévin Vilela Pinto

25

การใช้ [innerHTML] โดยตรงโดยไม่ต้องใช้ DOM sanitizer ของ Angular ไม่ใช่ตัวเลือกหากมีเนื้อหาที่ผู้ใช้สร้างขึ้น safeHtml ไปป์ที่แนะนำโดย @ GünterZöchbauer ในคำตอบของเขาคือวิธีหนึ่งในการฆ่าเชื้อเนื้อหา คำสั่งต่อไปนี้เป็นอีกหนึ่ง:

import { Directive, ElementRef, Input, OnChanges, Sanitizer, SecurityContext,
  SimpleChanges } from '@angular/core';

// Sets the element's innerHTML to a sanitized version of [safeHtml]
@Directive({ selector: '[safeHtml]' })
export class HtmlDirective implements OnChanges {
  @Input() safeHtml: string;

  constructor(private elementRef: ElementRef, private sanitizer: Sanitizer) {}

  ngOnChanges(changes: SimpleChanges): any {
    if ('safeHtml' in changes) {
      this.elementRef.nativeElement.innerHTML =
        this.sanitizer.sanitize(SecurityContext.HTML, this.safeHtml);
    }
  }
}

เพื่อนำมาใช้

<div [safeHtml]="myVal"></div>

ฉันพยายามใช้สิ่งนี้ แต่ได้รับข้อผิดพลาดดังต่อไปนี้Can't bind to 'safeHtml' since it isn't a known property of 'div'. ng-version 2.4.4
LearnToday

1
@ObasiObenyOj คุณยังสามารถทำได้โดยไม่ต้องใช้คำสั่งแยกต่างหากหากเป็นกรณี จำกัด constructor( private sanitizer: Sanitizer) {} และผูกผลในสิ่งที่คุณต้องการนอกจากนี้การใช้งาน ElementRef ก็ไม่ได้รับผลกระทบอย่างมาก
Vale Steve

22

โปรดอ้างอิงคำตอบอื่น ๆ ที่เป็นปัจจุบันมากขึ้น

สิ่งนี้ใช้ได้สำหรับฉัน: <div innerHTML = "{{ myVal }}"></div>(Angular2, Alpha 33)

อ้างอิงจาก SO อื่น: การแทรก HTML จากเซิร์ฟเวอร์ไปยัง DOM ด้วย angular2 (การจัดการ DOM ทั่วไปใน Angular2) "inner-html" เทียบเท่ากับ "ng-bind-html" ใน Angular 1.X


วิธีที่ถูกต้องคือไม่มี {{}}: <div innerHTML = "myVal"> </div>
Christian Benseler

2
ใช้ไวยากรณ์การผูก [property] แทน {{interpolation}}
superluminary

นี่เป็นวิธีที่ผิดที่ควรทำและควรถูกลดระดับลง สิ่งนี้จะทำให้ html ทั้งหมดของคุณอยู่ในแอตทริบิวต์ div!
AsGoodAsItGets

11

เพียงเพื่อให้ได้คำตอบที่สมบูรณ์หากเนื้อหา html ของคุณอยู่ในตัวแปรองค์ประกอบคุณสามารถใช้:

<div [innerHTML]=componementVariableThatHasTheHtml></div>

10

ฉันขอโทษหากฉันพลาดจุดที่นี่ แต่ฉันอยากจะแนะนำวิธีการอื่น:

ฉันคิดว่าเป็นการดีกว่าที่จะส่งคืนข้อมูลดิบจากแอปพลิเคชันฝั่งเซิร์ฟเวอร์ของคุณและผูกไว้กับแม่แบบในฝั่งไคลเอ็นต์ สิ่งนี้ทำให้คำขอที่ว่องไวมากขึ้นเนื่องจากคุณส่งคืน json จากเซิร์ฟเวอร์ของคุณเท่านั้น

สำหรับฉันมันดูเหมือนจะไม่เหมาะสมที่จะใช้ Angular ถ้าสิ่งที่คุณทำคือดึงข้อมูล html จากเซิร์ฟเวอร์และทำการฉีด "ตามที่เป็น" ลงใน DOM

ฉันรู้ว่า Angular 1.x มีการเชื่อมโยง html แต่ฉันยังไม่เห็นคู่ใน Angular 2.0 พวกเขาอาจเพิ่มในภายหลังว่า อย่างไรก็ตามฉันยังคงพิจารณา data api สำหรับแอป Angular 2.0 ของคุณ

ฉันมีตัวอย่างสองสามตัวอย่างที่นี่และมีการเชื่อมโยงข้อมูลอย่างง่ายถ้าคุณสนใจ: http://www.syntaxsuccess.com/viewarticle/angular-2.0-examples


28
มีกรณีใช้แน่นอนที่คุณต้องการดึงข้อมูลและแสดง html ดิบ เช่นดึงชิ้นส่วนของบทความที่จัดรูปแบบจากระยะไกล
Alexander Chen

2
อีกสถานการณ์ที่ถูกละเลยบ่อยครั้งคือการปกป้องตรรกะทางธุรกิจในแม่แบบบางครั้งคุณไม่ต้องการให้ผู้ใช้ที่ไม่ได้รับอนุญาตดูตรรกะที่คุณใช้เพื่อแสดงข้อมูลดังนั้นคุณควรเตรียมมุมมองทางฝั่งเซิร์ฟเวอร์
Ayyash

2
นอกจากนี้ยังแสดงอีเมล HTML เช่น - จุดยุติธรรม / คำถามว่า!
darren

2
หากคุณไม่ได้รับคะแนน (ซึ่งคุณดูเหมือนจะเป็นของคุณเอง) แล้วทำไมต้องโพสต์คำตอบ? แน่นอนว่าจุดของแองกูลาร์คือการใช้เอ็นจิ้นการดูเพื่อเชื่อมโยงและแสดงข้อมูล แต่เมื่อพิจารณาจากความจริงที่ว่ามีแอปพลิเคชั่นมากมายที่อาจใช้แอปพลิเคชัน Angular เป็นไปได้จริงที่หนึ่งหรือสองของพวกเขาอาจมีข้อกำหนดว่าข้อมูลบางอย่างที่ต้องแสดงในใบสมัครของคุณอาจจัดรูปแบบ HTML แล้ว และอาจเป็นกรณีที่ผู้พัฒนาไม่สามารถควบคุมเนื้อหานั้นได้ ในคำอื่น ๆ ... คำถามที่เกี่ยวข้อง
Gregor

ยาเราก็ควรจะทิ้งเชิงมุมและใช้ JQuery เพราะ Jquery ไม่นี้สิ่งหนึ่งที่ดีกว่า ...
Simon_Weaver

9

คำตอบสั้น ๆ มีให้ที่นี่แล้ว: ใช้ <div [innerHTML]="yourHtml">เชื่อม

อย่างไรก็ตามคำแนะนำที่เหลือที่กล่าวถึงในที่นี้อาจทำให้เข้าใจผิด Angular มีกลไกการฆ่าเชื้อในตัวเมื่อคุณผูกคุณสมบัติเช่นนั้น เนื่องจาก Angular ไม่ใช่ห้องสมุดที่มีการฆ่าเชื้อโดยเฉพาะจึงมีเนื้อหาที่น่าสงสัยอย่างมากที่จะไม่รับความเสี่ยงใด ๆ ตัวอย่างเช่นจะทำให้เนื้อหา SVG ทั้งหมดถูกทำให้เป็นสตริงว่าง

คุณอาจได้ยินคำแนะนำในการ "ฆ่าเชื้อ" เนื้อหาของคุณโดยใช้DomSanitizerเพื่อทำเครื่องหมายเนื้อหาว่าปลอดภัยด้วยbypassSecurityTrustXXXวิธีการ นอกจากนี้ยังมีข้อเสนอแนะเพื่อใช้ไปป์ในการทำเช่นนั้นและมักจะเรียกว่าไปป์นั้นsafeHtmlนอกจากนี้ยังมีข้อเสนอแนะที่จะใช้ท่อที่จะทำและท่อที่มักจะถูกเรียกว่า

ทั้งหมดนี้ทำให้เข้าใจผิดเพราะจริงๆแล้วมันผ่านการฆ่าเชื้อไม่ได้ฆ่าเนื้อหาของคุณ นี่อาจเป็นปัญหาด้านความปลอดภัยเพราะหากคุณเคยทำสิ่งนี้กับผู้ใช้ที่ให้เนื้อหาหรือสิ่งใดก็ตามที่คุณไม่แน่ใจคุณเปิดตัวเองขึ้นมาเพื่อโจมตีโค้ดอันตราย

ถ้า Angular ลบบางสิ่งที่คุณต้องการด้วยการฆ่าเชื้อในตัว - สิ่งที่คุณสามารถทำได้แทนที่จะปิดการใช้งานนั้นคือมอบหมายการฆ่าเชื้อที่เกิดขึ้นจริงให้กับห้องสมุดเฉพาะที่ดีต่องานนั้น ตัวอย่างเช่น - DOMPurify

ฉันได้สร้างไลบรารี่ของมันเพื่อให้สามารถใช้กับ Angular ได้อย่างง่ายดาย: https://github.com/TinkoffCreditSystems/ng-dompurify

นอกจากนี้ยังมีไปป์เพื่อฆ่าเชื้อ HTML อย่างชัดเจน:

<div [innerHtml]="value | dompurify"></div>

ข้อแตกต่างของท่อที่แนะนำในที่นี้คือการทำความสะอาดผ่าน DOMPurify จริง ๆ แล้วทำงานได้กับ SVG

สิ่งหนึ่งที่ต้องจำไว้คือ DOMPurify นั้นยอดเยี่ยมสำหรับการฆ่าเชื้อ HTML / SVG แต่ไม่ใช่ CSS ดังนั้นคุณสามารถให้บริการการฆ่าเชื้อ CSS ของ Angular เพื่อจัดการ CSS:

import {NgModule, ɵ_sanitizeStyle} from '@angular/core';
import {SANITIZE_STYLE} from '@tinkoff/ng-dompurify';

@NgModule({
    // ...
    providers: [
        {
            provide: SANITIZE_STYLE,
            useValue: ɵ_sanitizeStyle,
        },
    ],
    // ...
})
export class AppModule {}

มันเป็นɵคำนำหน้าภายใน - แต่นี่คือสิ่งที่ทีม Angular ใช้มันในแพ็คเกจของตัวเองเช่นกัน ไลบรารีดังกล่าวยังใช้งานได้กับ Angular Universal และสภาพแวดล้อมการ Renedring ฝั่งเซิร์ฟเวอร์


5

เพียงใช้[innerHTML]แอตทริบิวต์ในHTMLของคุณมีลักษณะดังนี้:

<div [innerHTML]="myVal"></div>

เคยมีคุณสมบัติในส่วนประกอบของคุณที่มีมาร์กอัป html หรือเอนทิตีที่คุณต้องการแสดงในเทมเพลตของคุณหรือไม่? การแก้ไขแบบดั้งเดิมจะไม่ทำงาน แต่การเชื่อมโยงคุณสมบัติ innerHTML เข้ามาช่วย

การใช้{{myVal}} ไม่ทำงานอย่างที่คาดไว้! นี้จะไม่ได้รับแท็ก HTML เช่น<p>, <strong>ฯลฯ และผ่านมันเป็นเพียงสตริง ...

ลองนึกภาพคุณมีรหัสนี้ในองค์ประกอบของคุณ:

const myVal:string ='<strong>Stackoverflow</strong> is <em>helpful!</em>'

หากคุณใช้{{myVal}}คุณจะได้รับสิ่งนี้ในมุมมอง:

<strong>Stackoverflow</strong> is <em>helpful!</em>

แต่ใช้ [innerHTML]="myVal"ทำให้ผลลัพธ์ตามที่คาดไว้เช่นนี้:

Stackoverflowมีประโยชน์!


คุณจะแสดงเนื้อหาของคุณอย่างไรถ้าคุณต้องการโดยไม่มีคอนเทนเนอร์ div? เป็นไปได้ไหม
ΕГИІИО

3

คุณสามารถใช้หลายไพพ์เพื่อสไตล์ลิงค์และ HTML ดังต่อไปนี้ใน. html

<div [innerHTML]="announcementContent | safeUrl| safeHtml">
                    </div>

และใน. ts ไปป์สำหรับการฆ่าเชื้อ 'URL'

import { Component, Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';

@Pipe({ name: 'safeUrl' })
export class SafeUrlPipe implements PipeTransform {
    constructor(private sanitizer: DomSanitizer) {}
    transform(url) {
        return this.sanitizer.bypassSecurityTrustResourceUrl(url);
    }
}

pipe สำหรับ 'HTML' sanitizer

import { Component, Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';

@Pipe({
    name: 'safeHtml'
})
export class SafeHtmlPipe implements PipeTransform {
    constructor(private sanitized: DomSanitizer) {}
    transform(value) {
        return this.sanitized.bypassSecurityTrustHtml(value);
    }
}

การดำเนินการนี้จะนำไปใช้กับทั้งคู่โดยไม่รบกวนลักษณะการเชื่อมโยงและเหตุการณ์การคลิก


2

 <div [innerHTML]="HtmlPrint"></div><br>

The InnerHtmlเป็นทรัพย์สินของ HTML องค์ประกอบซึ่งจะช่วยให้คุณสามารถตั้งค่ามันเป็น HTML เนื้อหา programatically นอกจากนี้ยังมีคุณสมบัติ InnerText ซึ่งกำหนดเนื้อหาเป็นข้อความธรรมดา

[attributeName]="value"วงเล็บกล่องรอบแอตทริบิวต์กำหนดอินพุตผูกพันเชิงมุม นั่นหมายความว่าค่าของคุณสมบัติ (ใน case InnerHtml ของคุณ) ถูกผูกไว้กับนิพจน์ที่กำหนดเมื่อการเปลี่ยนแปลงผลลัพธ์นิพจน์ค่าคุณสมบัติจะเปลี่ยนเช่นกัน

ดังนั้นโดยพื้นฐานแล้ว[innerHtml]อนุญาตให้คุณผูกและเปลี่ยน html-conent ของ HTML-Element ที่กำหนดไว้แบบไดนามิก


1

ในAngular 2คุณสามารถทำการผูกได้ 3 ประเภท:

  • [property]="expression"-> คุณสมบัติ html ใด ๆ สามารถลิงก์ไปยัง
    นิพจน์ได้ ในกรณีนี้หากนิพจน์การเปลี่ยนแปลงคุณสมบัติจะอัปเดต แต่มันไม่ทำงานในทางอื่น
  • (event)="expression" -> เมื่อเหตุการณ์เปิดใช้งานเรียกใช้งานนิพจน์
  • [(ngModel)]="property"-> ผูกคุณสมบัติจาก js (หรือ ts) ถึง html การปรับปรุงใด ๆ เกี่ยวกับคุณสมบัตินี้จะเห็นได้ทุกที่

นิพจน์สามารถเป็นค่าคุณลักษณะหรือวิธีการ ตัวอย่างเช่น: '4', 'controller.var', 'getValue ()'

ตัวอย่างที่นี่


0

วิธีการเพิ่มองค์ประกอบลงใน DOM แบบไดนามิกดังอธิบายใน Angular 2 doc คือการใช้คลาส ViewContainerRef จาก @ Angular / core

สิ่งที่คุณต้องทำคือการประกาศคำสั่งที่จะใช้ ViewContainerRef และทำหน้าที่เหมือนตัวแทนใน DOM ของคุณ

คำสั่ง

import { Directive, ViewContainerRef } from '@angular/core';

@Directive({
  selector: '[appInject]'
})
export class InjectDirective {

  constructor(public viewContainerRef: ViewContainerRef) { }

}

จากนั้นในเทมเพลตที่คุณต้องการฉีดองค์ประกอบ:

HTML

<div class="where_you_want_to_inject">    
  <ng-template appInject></ng-template>
</div>

จากนั้นจากรหัสองค์ประกอบที่ฉีดคุณจะฉีดองค์ประกอบที่มี HTML ที่คุณต้องการ:

import { Component, OnInit, ViewChild, ComponentFactoryResolver } from '@angular/core';
import { InjectDirective } from '../inject.directive';
import { InjectedComponent } from '../injected/injected.component';

@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.css']
})
export class ParentComponent implements OnInit {

  @ViewChild(InjectDirective) injectComp: InjectDirective;

  constructor(private _componentFactoryResolver: ComponentFactoryResolver) {
  }

  ngOnInit() {
  }

  public addComp() {
    const componentFactory = this._componentFactoryResolver.resolveComponentFactory(InjectedComponent);
    const viewContainerRef = this.injectComp.viewContainerRef;
    const componentRef = viewContainerRef.createComponent(componentFactory);
  }

  public removeComp() {
    const componentFactory = this._componentFactoryResolver.resolveComponentFactory(InjectedComponent);
    const viewContainerRef = this.injectComp.viewContainerRef;
    const componentRef = viewContainerRef.remove();
  }

}

ฉันได้เพิ่มแอปตัวอย่างที่ทำงานได้อย่างสมบูรณ์บนAngular 2 เพิ่มคอมโพเนนต์ไปยังการสาธิต DOM แบบไดนามิก


0

คุณสามารถใช้วิธีการต่าง ๆ เพื่อให้ได้โซลูชัน ดังที่ได้กล่าวแล้วในคำตอบที่ได้รับอนุมัติคุณสามารถใช้:

<div [innerHTML]="myVal"></div>

ขึ้นอยู่กับสิ่งที่คุณพยายามที่จะบรรลุคุณยังสามารถลองสิ่งอื่น ๆ เช่น javascript DOM (ไม่แนะนำการดำเนินการ DOM จะช้า):

การเสนอ

<div id="test"></test>

ตัวแทน

var p = document.getElementsById("test");
p.outerHTML = myVal;

การผูกทรัพย์สิน

Javascript DOM Outer HTML


ไม่ว่าการดำเนินการของ DOM จะช้ากว่าเชิงมุมหรือไม่ก็ตามการดำเนินการโดยใช้getElementsByIdหรือวิธีการเลือกอื่น ๆ นั้นไม่ดีเพราะอาจจับองค์ประกอบที่เป็นขององค์ประกอบที่แตกต่างกันโดยสิ้นเชิงหากมีองค์ประกอบที่มีรหัสเดียวกัน (หรือเกณฑ์อื่น ๆ )
Aviad P.

นอกจากนี้มันยังทำงานได้อย่างสมบูรณ์นอกเขตเชิงมุมดังนั้นการเปลี่ยนแปลงจะไม่ถูกหยิบขึ้นมา
Philipp Meissner

0

เราสามารถส่งเนื้อหา html ไปยังinnerHTMLทรัพย์สินเพื่อแสดงเนื้อหา html ไดนามิกได้ตลอดเวลา แต่เนื้อหา html ไดนามิกนั้นสามารถติดเชื้อหรือเป็นอันตรายได้เช่นกัน ดังนั้นก่อนที่จะส่งเนื้อหาแบบไดนามิกให้innerHTMLเราควรตรวจสอบให้แน่ใจว่าเนื้อหานั้นถูกทำให้สะอาด (โดยใช้DOMSanitizer) เพื่อให้เราสามารถหลบหนีเนื้อหาที่เป็นอันตรายทั้งหมดได้

ลองท่อด้านล่าง:

import { Pipe, PipeTransform } from "@angular/core";
import { DomSanitizer } from "@angular/platform-browser";

@Pipe({name: 'safeHtml'})
export class SafeHtmlPipe implements PipeTransform {
    constructor(private sanitized: DomSanitizer) {
    }
    transform(value: string) {
        return this.sanitized.bypassSecurityTrustHtml(value);
    }
}

Usage:
<div [innerHTML]="content | safeHtml"></div>

นี่เป็นสิ่งจำเป็นแม้ว่าคุณจะคิดว่าไม่ใช่ ตัวอย่างstyle: background-colorของทุกสิ่งสามารถถูกถอดออกและดังนั้นจึงเป็นการดีที่สุดที่จะเริ่มใช้สิ่งนี้ตั้งแต่เริ่มต้นมิฉะนั้นคุณจะสับสนมากในภายหลัง
Simon_Weaver

สิ่งที่ฉันเข้าใจคือสคริปต์นี้คือการอนุญาตเนื้อหาที่เป็นอันตรายทั้งหมด (bypassSecurityTrustHtml) ตามที่คุณชี้สิ่งนี้ฉันคิดว่าไม่จำเป็นต้องใช้ไพพ์นี้จนกว่าคุณจะเชื่อถือแหล่งที่มา การอ้างอิงถึง: angular.io/api/platform-browser/DomSanitizer#security-risk
Sae

0

หากคุณต้องการใน Angular 2 หรือ Angular 4 และต้องการเก็บ inline CSS ไว้คุณสามารถใช้

<div [innerHTML]="theHtmlString | keepHtml"></div>

สิ่งนี้ทำให้ฉันมีข้อผิดพลาด `Uncaught (ตามสัญญา): ข้อผิดพลาด: ข้อผิดพลาดในการแยกวิเคราะห์แม่แบบ: ไม่พบ pipe 'keepHtml'`
Praveen

นำเข้า {Pipe, PipeTransform} จาก "@ angular / core";
Jay Momaya

0

คุณยังสามารถผูกคุณสมบัติคลาสองค์ประกอบเชิงมุมกับเทมเพลตโดยใช้รูปแบบบัญญัติดังนี้

<div bind-innerHTML="theHtmlString"></div>

เอกสารเชิงมุม: https://angular.io/guide/template-syntax#property-binding-property

ดูตัวอย่าง stackblitz ที่ใช้งานได้ที่นี่


0

ทำงานใน Angular v2.1.1

<div [innerHTML]="variable or htmlString">
</div>

2
สิ่งนี้สร้าง: <div _ngcontent-luf-0=""></div>สำหรับฉัน divเป็นที่ว่างเปล่า
Scott Marcus

-2

หากคุณมีเทมเพลตในแอปพลิเคชันเชิงมุม (หรือกรอบใด ๆ ) และคุณส่งคืนเท็มเพลต HTML จากแบ็กเอนด์ผ่านการร้องขอ / ตอบกลับ HTTP คุณกำลังผสมเทมเพลตระหว่างส่วนหน้าและส่วนหลัง

ทำไมไม่เพียงแค่ปล่อยสิ่งเทมเพลตไว้ในส่วนหน้า (ฉันอยากจะแนะนำ) หรือในแบ็กเอนด์ (imo ที่ค่อนข้างโปร่งใส)

และถ้าคุณเก็บเท็มเพลตไว้ในส่วนหน้าทำไมไม่เพียงแค่ตอบสนองกับ JSON เพื่อขอแบ็กเอนด์ คุณไม่จำเป็นต้องใช้โครงสร้าง RESTful แต่การรักษาเทมเพลตไว้ด้านหนึ่งจะทำให้โค้ดของคุณโปร่งใสยิ่งขึ้น

วิธีนี้จะคืนเงินเมื่อมีคนอื่นต้องรับมือกับรหัสของคุณ (หรือแม้แต่ตัวคุณเองก็กำลังป้อนรหัสของคุณเองหลังจากผ่านไประยะหนึ่ง)!

ถ้าคุณทำถูกต้องคุณจะมีส่วนประกอบขนาดเล็กที่มีแม่แบบขนาดเล็กและที่ดีที่สุดถ้ารหัสของคุณคือ imba คนที่ไม่รู้ภาษาการเข้ารหัสจะสามารถเข้าใจแม่แบบและตรรกะของคุณได้! นอกจากนี้รักษาฟังก์ชั่น / วิธีการของคุณให้เล็กที่สุดเท่าที่จะทำได้ ในที่สุดคุณจะพบว่าการบำรุงรักษาการปรับโครงสร้างการตรวจสอบและการเพิ่มคุณสมบัติจะง่ายกว่ามากเมื่อเทียบกับฟังก์ชั่น / วิธีการ / ชั้นเรียนขนาดใหญ่และการผสมการสร้างเทมเพลตและตรรกะระหว่างส่วนหน้าและส่วนหลัง - ถ้าส่วนหน้าของคุณจะต้องมีความยืดหยุ่นมากขึ้น (เช่นการเขียนส่วนหน้าของ Android หรือเปลี่ยนไปใช้ส่วนหน้าแบบอื่น)

ปรัชญาผู้ชาย :)

ป.ล. : คุณไม่ต้องใช้โค้ดที่สะอาด 100% เพราะมันแพงมาก - โดยเฉพาะถ้าคุณต้องกระตุ้นให้สมาชิกในทีม;) แต่: คุณควรหาสมดุลที่ดีระหว่างแนวทางในการทำความสะอาดโค้ดกับสิ่งที่คุณมี สวยสะอาดอยู่แล้ว)

ตรวจสอบหนังสือถ้าคุณสามารถและปล่อยให้มันเข้าสู่จิตวิญญาณของคุณ: https://de.wikipedia.org/wiki/Clean_Code


บางครั้งจำเป็นต้องรับ HTML จากฝั่งเซิร์ฟเวอร์เมื่อคุณจัดการกับ API เก่าเช่นใน SOAP ฉันกำลังทำงานกับโครงการหนึ่งของฉันกับ BSC (ตลาดหลักทรัพย์ Bharat) และพวกเขาส่งคืนรหัส HTML ของหน้าธนาคารในขณะที่ชำระเงิน ดังนั้นคุณไม่สามารถเปลี่ยน API ได้คุณต้องอัปเดตรหัสของคุณ
Mahendra Waykos

คุณสามารถเขียนมิดเดิลแวร์ซึ่งทำการสืบค้น soap api และให้ผลลัพธ์ที่แยกในซ็อกเก็ต การบริโภคและการดึงข้อมูลผ่านสบู่อาจเป็นความเจ็บปวด
Guntram

กรณีการใช้งานที่ชัดเจนมากจริงๆสำหรับมาร์กอัปดิบคือเมื่อมาร์กอัปของคุณมาจาก CMS และเขียนด้วยโปรแกรมแก้ไขแบบ WYSIWYG คุณอาจแสดงจุดปลายหลายจุดจาก CMS ที่ไม่มีหัวขาด สิ่งนี้เป็นสาเหตุที่ทำให้เครื่องยนต์ทุกเทมเพลตมีตัวเลือกสำหรับมาร์กอัปดิบ
gburton
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.