Angular 2 - innerHTML ใส่สไตล์


170

ฉันได้รับโค้ด HTML จากการโทร HTTP ฉันใส่บล็อก HTML ในตัวแปรและใส่ไว้ในหน้าของฉันด้วย [innerHTML] แต่ฉันไม่สามารถจัดสไตล์บล็อก HTML ที่แทรกไว้ได้ ไม่มีใครมีข้อเสนอแนะใด ๆ ว่าฉันจะบรรลุเป้าหมายนี้ได้อย่างไร?

@Component({selector: 'calendar',
template: '<div [innerHTML]="calendar"></div>',
providers:[HomeService], 
styles: [` 
h3 {color:red;}
`})

HTML ที่ฉันต้องการสไตล์คือบล็อกที่มีอยู่ในตัวแปร "ปฏิทิน"


สไตล์จากที่ไหน จากภายในองค์ประกอบหรือจากรูปแบบที่เพิ่มเข้ามาindex.html?
GünterZöchbauer

คุณหมายถึงcan not style the inserted HTML blockอะไร แสดงให้เราเห็นสิ่งที่ทำไปด้วยรหัสขนาดเล็ก
micronyks

ฉันได้อัพเดทโพสต์ของฉันด้วยโค้ดขนาดเล็ก! :) ขอบคุณ
Jakob Svenningsson

1
ฉันเพิ่มลิงก์ Plunker ไปยังคำตอบของฉัน
GünterZöchbauer

@GünterZöchbauerจะเกิดอะไรขึ้นหากรหัส HTML มีอินไลน์ css มันจะแสดงผลอย่างไร
iniravpatel

คำตอบ:


320

อัปเดต 2 ::slotted

::slotted ขณะนี้ได้รับการสนับสนุนโดยเบราว์เซอร์ใหม่ทั้งหมดและสามารถใช้ได้กับ ViewEncapsulation.ShadowDom

https://developer.mozilla.org/en-US/docs/Web/CSS/::slotted

อัปเดต 1 :: ng-deep

/deep/::ng-deepได้รับการยกเลิกและถูกแทนที่ด้วย

::ng-deep ทำเครื่องหมายว่าเลิกใช้แล้ว แต่ยังไม่มีการแทนที่

เมื่อViewEncapsulation.Nativeได้รับการสนับสนุนอย่างถูกต้องโดยเบราว์เซอร์ทั้งหมดและสนับสนุนการกำหนดสไตล์ตามขอบเขตเงาของ DOM เงา::ng-deepอาจจะถูกยกเลิก

เป็นต้นฉบับ

Angular เพิ่มคลาส CSS ทุกชนิดลงใน HTML ซึ่งเพิ่มไปยัง DOM เพื่อเลียนแบบการห่อหุ้มเงาของ CSS CSS เพื่อป้องกันไม่ให้สไตล์การไหลเข้าและออกขององค์ประกอบ Angular ยังเขียน CSS ที่คุณเพิ่มเพื่อให้ตรงกับคลาสที่เพิ่มเหล่านี้ สำหรับ HTML ที่เพิ่มโดยใช้[innerHTML]คลาสเหล่านี้จะไม่ถูกเพิ่มและ CSS ที่เขียนใหม่ไม่ตรงกัน

เป็นวิธีแก้ปัญหาลอง

  • สำหรับ CSS ถูกเพิ่มไปยังองค์ประกอบ
/* :host /deep/ mySelector { */
:host ::ng-deep mySelector { 
  background-color: blue;
}
  • สำหรับ CSS ถูกเพิ่มเข้าไป index.html
/* body /deep/ mySelector { */
body ::ng-deep mySelector {
  background-color: green;
}

>>>(และเทียบเท่า/deep/แต่/deep/ทำงานได้ดีขึ้นกับ SASS) และ::shadowถูกเพิ่มเข้ามาใน 2.0.0-beta.10 พวกมันคล้ายกับ combinators DOM DOM เงา (ซึ่งเลิกใช้แล้ว) และทำงานเฉพาะกับencapsulation: ViewEncapsulation.Emulatedซึ่งเป็นค่าเริ่มต้นใน Angular2 พวกเขาอาจทำงานด้วยViewEncapsulation.Noneแต่ถูกละเว้นเพียงเพราะไม่จำเป็น Combinators เหล่านี้เป็นเพียงวิธีการแก้ปัญหาระดับกลางจนกว่าจะรองรับคุณสมบัติขั้นสูงสำหรับการออกแบบข้ามองค์ประกอบ

อีกวิธีคือการใช้

@Component({
  ...
  encapsulation: ViewEncapsulation.None,
})

สำหรับส่วนประกอบทั้งหมดที่บล็อก CSS ของคุณ (ขึ้นอยู่กับตำแหน่งที่คุณเพิ่ม CSS และตำแหน่งที่ HTML ที่คุณต้องการจัดสไตล์ - อาจเป็นส่วนประกอบทั้งหมดในแอปพลิเคชันของคุณ)

ปรับปรุง

ตัวอย่าง Plunker


6
แค่โน้ตสำหรับทุกคนสิ่งนี้ไม่สามารถใช้ได้กับ node-sass หรือ styleUrl เฉพาะในรูปแบบ: [... ]
yeliha

12
ด้วยการใช้งาน SASS /deep/แทน>>>
GünterZöchbauer

1
คุณไม่สามารถมีคำสั่งหรือ compinents ในเนื้อหาที่เพิ่มเข้ามาด้วยinneeHTML
GünterZöchbauer

1
หาก HTML ที่ได้รับจากการโทร HTTP มีขนาดใหญ่และมีอินไลน์ css ว่าจะเป็นไปได้อย่างไรเนื่องจากฉันไม่มีรูปแบบที่กำหนดไว้ล่วงหน้าฉันจะได้รับจากอินไลน์ css เท่านั้น @ GünterZöchbauer
iniravpatel

1
บันทึกวันใน Angular 8! Thanx เป็นการยากที่จะได้รับคำถามเพื่อค้นหาคำตอบนี้!
Pianoman

12

ทางออกที่ง่ายที่คุณต้องทำคือ

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

constructor(private sanitizer: DomSanitizer){}

transformYourHtml(htmlTextWithStyle) {
    return this.sanitizer.bypassSecurityTrustHtml(htmlTextWithStyle);
}

2

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

// inside component class...

constructor(private hostRef: ElementRef) { }

getContentAttr(): string {
  const attrs = this.hostRef.nativeElement.attributes
  for (let i = 0, l = attrs.length; i < l; i++) {
    if (attrs[i].name.startsWith('_nghost-c')) {
      return `_ngcontent-c${attrs[i].name.substring(9)}`
    }
  }
}

ngAfterViewInit() {
  // dynamically add HTML element
  dynamicallyAddedHtmlElement.setAttribute(this.getContentAttr(), '')
}

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


2

เราดึงในเนื้อหาบ่อยจาก CMS [innerHTML]="content.title"ของเราเป็น เราวางคลาสที่จำเป็นลงในstyles.scssไฟล์รูทของแอปพลิเคชันแทนที่จะอยู่ในไฟล์ scss ของคอมโพเนนต์ CMS ของเราตั้งใจที่จะแยกสไตล์ในบรรทัดดังนั้นเราต้องเตรียมคลาสที่ผู้เขียนสามารถใช้ในเนื้อหาของพวกเขา โปรดจำไว้ว่าการใช้{{content.title}}ในเทมเพลตจะไม่แสดงผล html จากเนื้อหา


-3

หากคุณใช้ sass เป็นตัวประมวลผลสไตล์คุณสามารถสลับกลับไปเป็นคอมไพเลอร์ Sass ดั้งเดิมสำหรับการพึ่งพา dev โดย:

npm install node-sass --save-dev

เพื่อให้คุณสามารถใช้ / ลึก / เพื่อการพัฒนา

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