Angular 응용 프로그램을 작성 중이며 표시하려는 HTML 응답이 있습니다.
어떻게합니까? 바인딩 구문을 사용하면 {{myVal}}
모든 HTML 문자를 인코딩합니다 (물론).
나는 바인딩 어떻게 든 필요 innerHTML
의를 div
변수 값으로.
Angular 응용 프로그램을 작성 중이며 표시하려는 HTML 응답이 있습니다.
어떻게합니까? 바인딩 구문을 사용하면 {{myVal}}
모든 HTML 문자를 인코딩합니다 (물론).
나는 바인딩 어떻게 든 필요 innerHTML
의를 div
변수 값으로.
답변:
Angular 2.0.0 및 Angular 4.0.0 최종
안전한 콘텐츠를 위해
<div [innerHTML]="myVal"></div>
DOMSanitizer
잠재적 인 안전하지 않은 HTML은 Angulars DOM 소독제를 사용하여 명시 적으로 신뢰할 수있는 것으로 표시되어야하므로 잠재적으로 안전하지 않은 콘텐츠 부분을 제거하지 않습니다
<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>
Angular는에서 Angular 관련 항목을 처리하지 않습니다foo
. Angular는 빌드시 Angular 특정 마크 업을 생성 된 코드로 대체합니다. 런타임에 추가 된 마크 업은 Angular에 의해 처리되지 않습니다 .
Angular 관련 마크 업 (속성 또는 값 바인딩, 구성 요소, 지시문, 파이프 등)이 포함 된 HTML을 추가하려면 런타임에 동적 모듈을 추가하고 구성 요소를 컴파일해야합니다. 이 답변은 자세한 내용을 제공합니다. 동적 템플릿을 사용하여 동적 구성 요소를 Angular 2.0으로 컴파일하는 방법은 무엇입니까?
import { BrowserModule, DomSanitizer } from '@angular/platform-browser'
import { Pipe } from '@angular/core'
[innerHtml]
대부분의 경우 훌륭한 옵션이지만 실제로 큰 문자열이나 HTML로 하드 코딩 된 스타일링이 필요한 경우 실패합니다.
다른 접근법을 공유하고 싶습니다.
html 파일에 div를 만들고 ID를 지정하기 만하면됩니다.
<div #dataContainer></div>
그런 다음 Angular 2 구성 요소에서이 객체에 대한 참조를 작성하십시오 (TypeScript here).
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 환경에서 사용하는 방법 일뿐입니다. 코드를 더 복잡하게 만들지 않기 때문에 권장하지 않지만 때로는 다른 옵션이 없습니다.
nativeElement
이 나쁜 습관으로 간주되는 속성에 직접 액세스한다는 점을 제외하고 다른 솔루션과의 차이점은 없습니다 . 나는 [innerHTML]="..."
후드에서 똑같은 것을 확신 하지만 좋은 Angular2 연습 방식으로 확신합니다.
[innerHTML]
Angular2에서 큰 문자열에 문제가 있습니까?
[innerHtml]
HTML에 하드 코딩 된 스타일을 제거합니다. wysiwyg 편집기를 통합하려면 여기에 나열된 접근 방식을 사용해야했습니다.
[innerHTML]
접근 방식은 그렇지 않았습니다.
angular2@2.0.0-alpha.44에서 :
를 {{interpolation}}
사용할 때 HTML 바인딩이 작동하지 않습니다 . 대신 "표현식"을 사용하십시오.
무효
<p [innerHTML]="{{item.anleser}}"></p>
-> 오류 발생 (예상 식 대신 보간)
옳은
<p [innerHTML]="item.anleser"></p>
-> 이것이 올바른 방법입니다.
다음과 같이 표현식에 요소를 추가 할 수 있습니다.
<p [innerHTML]="'<b>'+item.anleser+'</b>'"></p>
힌트
보안을 위해 위생 처리를 제외하고 Angular는 HTML을 사용하여 추가 [innerHTML]
하거나 다른 방법으로 동적으로 추가 한 HTML을 element.appenChild()
처리하지 않습니다.
이러한 작업은 HTML이 구성 요소 템플릿에 정적으로 추가 된 경우에만 작동합니다. 이것이 필요한 경우 동적 템플릿을 어떻게 사용 / 생성하여 Angular 2.0으로 동적 컴포넌트를 컴파일 할 수 있습니까?에 설명 된대로 런타임에 컴포넌트를 작성할 수 있습니다 .
Angular의 DOM 소독제를 사용하지 않고 직접 [innerHTML]을 사용하는 것은 사용자가 만든 컨텐츠를 포함하는 경우 옵션이 아닙니다. @ GünterZöchbauer 가 그의 답변에서 제안한 safeHtml 파이프 는 내용을 살균하는 방법 중 하나입니다. 다음 지시어는 또 다른 지시어입니다.
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
constructor( private sanitizer: Sanitizer) {}
필요한 결과에 결과를 바인딩 할 수 있으며 ElementRef의 사용도 강력하게 권장되지 않습니다.
최신의 다른 답변을 참조하십시오.
이것은 나를 위해 작동합니다 : <div innerHTML = "{{ myVal }}"></div>
(Angular2, Alpha 33)
또 다른 SO : Angular2 (Angular2의 일반적인 DOM 조작)를 사용하여 서버에서 DOM으로 HTML 삽입하기 "inner-html"은 Angular 1.X의 "ng-bind-html"과 같습니다.
여기서 요점을 놓치면 사과하지만 다른 접근법을 추천하고 싶습니다.
서버 측 응용 프로그램에서 원시 데이터를 반환하고 클라이언트 측의 템플릿에 바인딩하는 것이 좋습니다. 이것은 서버에서 json 만 반환하기 때문에 더 민첩한 요청을 만듭니다.
나에게 서버에서 html을 가져 와서 DOM에 "있는 그대로"주입하면 Angular를 사용하는 것이 의미가없는 것처럼 보입니다.
Angular 1.x에 html 바인딩이 있다는 것을 알고 있지만 Angular 2.0에서는 아직 대응하지 못했습니다. 그래도 나중에 추가 할 수 있습니다. 어쨌든, 여전히 Angular 2.0 앱의 데이터 API를 고려할 것입니다.
관심이 있다면 여기에 간단한 데이터 바인딩과 함께 몇 가지 샘플이 있습니다 .http : //www.syntaxsuccess.com/viewarticle/angular-2.0-examples
짧은 대답은 이미 여기에 제공되었습니다 : <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 / SVG를 삭제하는 데 유용하지만 CSS는 아닙니다. 따라서 Angular의 CSS 소독제를 제공하여 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 환경에서도 작동합니다.
다음과 같이 HTML[innerHTML]
에서 속성을 사용 하십시오 .
<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 가 도움이됩니다!
.html에서 다음과 같이 스타일, 링크 및 HTML에 여러 파이프를 적용 할 수 있습니다.
<div [innerHTML]="announcementContent | safeUrl| safeHtml">
</div>
'URL'소독제 .ts 파이프
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);
}
}
'HTML'소독제 파이프
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);
}
}
스타일과 링크 클릭 이벤트를 방해하지 않으면 서 적용됩니다.
<div [innerHTML]="HtmlPrint"></div><br>
innerHTML을은 당신이 프로그래밍 방식으로 HTML 콘텐츠입니다 설정할 수 있습니다 HTML 요소의 속성입니다. 내용을 일반 텍스트로 정의하는 innerText 속성도 있습니다.
[attributeName]="value"
상자 브래킷, 특성을 둘러싼 각도 입력 결합 정의한다. 즉, 속성 값 (귀하의 innerHtml)이 주어진 식에 바인딩되어 있고 식 결과가 변경되면 속성 값도 변경됩니다.
따라서 기본적으로 [innerHtml]
주어진 HTML 요소의 html-conent를 바인딩하고 동적으로 변경할 수 있습니다.
Angular 2 에서는 3 가지 유형의 바인딩을 수행 할 수 있습니다.
[property]="expression"
-> 모든 HTML 속성은 (event)="expression"
-> 이벤트가 활성화되면 식을 실행합니다.[(ngModel)]="property"
-> 속성을 js (또는 ts)에서 html로 바인딩합니다. 이 속성에 대한 모든 업데이트는 어디에서나 볼 수 있습니다.표현식은 값, 속성 또는 메소드 일 수 있습니다. 예 : '4', 'controller.var', 'getValue ()'
여기 예
Angular 2 doc에서 설명한대로 DOM에 요소를 동적으로 추가하는 방법은 @ Angular / core의 ViewContainerRef 클래스를 사용하는 것입니다.
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 데모에 구성 요소를 동적으로 추가
솔루션을 달성하기 위해 여러 가지 접근 방식을 사용할 수 있습니다. 승인 된 답변에서 이미 언급했듯이 다음을 사용할 수 있습니다.
<div [innerHTML]="myVal"></div>
달성하려는 대상에 따라 javascript DOM과 같은 다른 작업을 시도 할 수도 있습니다 (권장되지 않음, DOM 작업이 느림).
표시
<div id="test"></test>
구성 요소
var p = document.getElementsById("test");
p.outerHTML = myVal;
getElementsById
동일한 ID (또는 다른 기준)를 가진 요소가 포함 된 완전히 다른 구성 요소에 속하는 요소를 캡처 할 수 있으므로 다른 선택 방법 을 사용 하거나 사용하여 수행하는 것은 좋지 않습니다.
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
모든 것들이 제거 될 수 있으므로 처음부터 이것을 사용하는 것이 가장 좋습니다. 그렇지 않으면 나중에 매우 혼란 스러울 것입니다.
Angular 2 또는 Angular 4에서 원하는 경우 인라인 CSS를 유지하려면 다음을 사용할 수 있습니다
<div [innerHTML]="theHtmlString | keepHtml"></div>
아래와 같이 표준 형식을 사용하여 각도 구성 요소 클래스 속성을 템플릿과 바인딩 할 수도 있습니다.
<div bind-innerHTML="theHtmlString"></div>
각도 문서 : https://angular.io/guide/template-syntax#property-binding-property
Angular v2.1.1에서 작업
<div [innerHTML]="variable or htmlString">
</div>
<div _ngcontent-luf-0=""></div>
나를 위해 생산 합니다. 는 div
비어 있습니다.
앵귤러 (또는 다른 프레임 워크) 응용 프로그램에 템플릿이 있고 HTTP 요청 / 응답을 통해 백엔드에서 HTML 템플릿을 반환하는 경우 프런트 엔드와 백엔드간에 템플릿이 혼합됩니다.
왜 템플릿을 프론트 엔드 (내가 제안 할 것) 나 백엔드 (꽤 불투명 한 imo)로 남겨 두지 않겠습니까?
프런트 엔드에 템플릿을 유지하는 경우 백엔드에 대한 요청에 대해 JSON으로 응답하는 것이 어떻습니까? RESTful 구조를 구현할 필요는 없지만 템플릿을 한쪽에 유지하면 코드가 더 투명 해집니다.
다른 사람이 귀하의 코드에 대처해야 할 때 (또는 자신이 잠시 후에 자신의 코드를 다시 입력하고있을 때) 상환됩니다!
올바르게 수행하면 작은 템플릿이있는 작은 구성 요소가 있으며, 코드가 imba 인 경우 코딩 언어를 모르는 사람이 템플릿과 논리를 이해할 수 있습니다. 따라서 기능 / 방법을 가능한 작게 유지하십시오. 결국 큰 기능 / 메소드 / 클래스에 비해 기능 유지, 리팩토링, 검토 및 추가가 훨씬 쉬워지고 프런트 엔드와 백엔드 사이의 템플릿과 논리가 혼합되어 백엔드의 논리를 최대한 유지한다는 것을 알게 될 것입니다 프론트 엔드가 더 유연해야하는 경우 (예 : 안드로이드 프론트 엔드 작성 또는 다른 프론트 엔드 프레임 워크로 전환)
철학, 남자 :)
추신 : 100 % 깨끗한 코드를 구현할 필요가 없습니다. 특히 비용이 많이 들기 때문입니다. 특히 팀원에게 동기를 부여 해야하는 경우;) : 더 깨끗한 코드에 대한 접근 방식과 가지고있는 것 사이에 균형이 맞아야합니다. 이미 꽤 깨끗합니다)
가능한 경우 책을 확인하고 당신의 영혼에 들어 오게하십시오 : https://de.wikipedia.org/wiki/Clean_Code