Development Tip

각도 HTML 바인딩

yourdevel 2020. 9. 29. 18:50
반응형

각도 HTML 바인딩


Angular 응용 프로그램을 작성 중이며 표시하려는 HTML 응답이 있습니다.

어떻게하나요? 단순히 바인딩 구문을 사용하면 {{myVal}}모든 HTML 문자를 인코딩합니다 (물론).

나는 바인딩 어떻게 든 필요 innerHTML의를 div변수 값으로.


올바른 구문은 다음과 같습니다.

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

작동 8.2.6

문서 참조


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가foo . Angular는 빌드시 Angular 특정 마크 업을 생성 된 코드로 대체합니다. 런타임에 추가 된 마크 업은 Angular에서 처리되지 않습니다 .

Angular 고유의 마크 업 (속성 또는 값 바인딩, 구성 요소, 지시문, 파이프 등)을 포함하는 HTML을 추가하려면 동적 모듈을 추가하고 런타임에 구성 요소를 컴파일해야합니다. 이 답변은 자세한 내용을 제공합니다 .Angular 2.0으로 동적 구성 요소를 컴파일하기 위해 동적 템플릿을 어떻게 사용 / 만들 수 있습니까?


[innerHtml] 대부분의 경우 훌륭한 옵션이지만, 정말 큰 문자열이나 html에서 하드 코딩 된 스타일이 필요할 때 실패합니다.

다른 접근 방식을 공유하고 싶습니다.

해야 할 일은 html 파일에 div를 만들고 ID를 부여하는 것입니다.

<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 환경에서 수행합니다. 코드를 더 복잡하게 만들기 때문에 권장하지 않지만 때로는 다른 옵션이 없습니다.

Angular 2-innerHTML 스타일링 도 참조하십시오.


angular2@2.0.0-alpha.44에서 :

{{interpolation}}사용할 때는 Html-Binding이 작동하지 않습니다 . 대신 "표현식"을 사용하십시오.

유효하지 않음

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

-> 오류 발생 (예상 표현식 대신 보간)

옳은

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

-> 이것이 올바른 방법입니다.

표현식에 다음과 같은 추가 요소를 추가 할 수 있습니다.

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

힌트

사용하여 추가 된 [innerHTML](또는 element.appenChild()유사하거나 유사한 다른 방법으로 동적으로 추가 된) HTML 은 보안 목적의 삭제를 제외하고 어떤 방식으로도 Angular에서 처리되지 않습니다.
이러한 작업은 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>

이것은 나를 위해 작동합니다 : <div innerHTML = "{{ myVal }}"></div>(Angular2, Alpha 33)

다른 SO에 따르면 : angular2 (Angular2의 일반적인 DOM 조작)를 사용하여 서버에서 DOM으로 HTML 삽입 , "inner-html"은 Angular 1.X의 "ng-bind-html"과 동일합니다.


완전한 답을 얻기 위해 html 콘텐츠가 구성 요소 변수에있는 경우 다음을 사용할 수도 있습니다.

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

여기서 요점을 놓친 경우 사과하지만 다른 접근 방식을 권장하고 싶습니다.

서버 측 애플리케이션에서 원시 데이터를 반환하고 클라이언트 측의 템플릿에 바인딩하는 것이 더 낫다고 생각합니다. 이렇게하면 서버에서 json 만 반환하므로보다 민첩한 요청이 가능합니다.

나에게 당신이하고있는 모든 것이 서버에서 html을 가져 와서 DOM에 "있는 그대로"주입하는 것이라면 Angular를 사용하는 것이 말이되지 않는 것 같습니다.

Angular 1.x에 html 바인딩이 있음을 알고 있지만 Angular 2.0에서는 아직 대응되지 않았습니다. 나중에 추가 할 수도 있습니다. 어쨌든 Angular 2.0 앱에 대한 데이터 API를 고려할 것입니다.

관심이 있으시면 간단한 데이터 바인딩과 함께 몇 가지 샘플이 있습니다. http://www.syntaxsuccess.com/viewarticle/angular-2.0-examples


다음과 같이 HTML[innerHTML] 에서 속성을 사용하기 만하면 됩니다.

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

템플릿에 표시해야하는 html 마크 업이나 엔티티가 포함 된 구성 요소에 속성이 있었습니까? 전통적인 보간법은 작동하지 않지만 innerHTML 속성 바인딩이 도움이됩니다.

Using {{myVal}} Does NOT work as expected! This won't pick up the HTML tags like <p>, <strong> etc and pass it only as strings...

Imagine you have this code in your component:

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

If you use {{myVal}}, you will get this in the view:

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

but using [innerHTML]="myVal"makes the result as expected like this:

Stackoverflow is helpful!


In Angular 2 you can do 3 types of bindings:

  • [property]="expression" -> Any html property can link to an
    expression. In this case, if expression changes property will update, but this doesn't work the other way.
  • (event)="expression" -> When event activates execute expression.
  • [(ngModel)]="property" -> Binds the property from js (or ts) to html. Any update on this property will be noticeable everywhere.

An expression can be a value, an attribute or a method. For example: '4', 'controller.var', 'getValue()'

Example here


We can always pass html content to innerHTML property to render html dynamic content but that dynamic html content can be infected or malicious also. So before passing dynamic content to innerHTML we should always make sure the content is sanitized (using DOMSanitizer) so that we can escaped all malicious content.

Try below pipe:

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>

Working in AngularJS v2.1.1

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

The way to dynamically add elements to DOM, as explained on Angular 2 doc, is by using ViewContainerRef class from @Angular/core.

What you have to do is to declare a directive that will implement ViewContainerRef and act like a placeholder on your DOM.

Directive

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

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

  constructor(public viewContainerRef: ViewContainerRef) { }

}

Then, in the template where you want to inject the component:

HTML

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

Then, from the injected component code, you will inject the component containing the HTML you want:

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();
  }

}

I added a fully working demo app on Angular 2 dynamically add component to DOM demo


You can use several approaches to achieve the solution. As already said in the approved answer, you can use:

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

depending on what you are trying to achieve, you can also try other things like javascript DOM (not recommended, DOM operations are slow):

Presentation

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

Component

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

Property Binding

Javascript DOM Outer HTML


If you want that in Angular 2 or Angular 4 and also want to keep inline CSS then you can use

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

You can use this method

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

or bind it by id

 <div #html></div>

and in the component

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;
    }
}

You can apply multiple pipe for style, link and HTML as following in .html

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

and in .ts pipe for 'URL' sanitizer

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 for '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);
    }
}

this will apply both without disturbing any style and link click event


If you have templates in your angular (or whatever framework) application, and you return HTML templates from your backend through a HTTP request/response, you are mixing up templates between the frontend and the backend.

Why not just leave the templating stuff either in the frontend (i would suggest that), or in the backend (pretty intransparent imo)?

And if you keep templates in the frontend, why not just respond with JSON for requests to the backend. You do not even have to implement a RESTful structure, but keeping templates on one side makes your code more transparent.

This will pay back when someone else has to cope with your code (or even you yourself are re-entering your own code after a while)!

If you do it right, you will have small components with small templates, and best of all, if your code is imba, someone who doesn't know coding languages will be able to understand your templates and your logic! So additionally, keep your functions/methods as small you can. You will eventually find out that maintaining, refactoring, reviewing, and adding features will be much easier compared to large functions/methods/classes and mixing up templating and logic between the frontend and the backend - and keep as much of the logic in the backend if your frontend needs to be more flexible (e.g. writing an android frontend or switching to a different frontend framework).

Philosophy, man :)

p.s.: you do not have to implement 100% clean code, because it is very expensive - especially if you have to motivate team members ;) but: you should find a good balance between an approach to cleaner code and what you have (maybe it is already pretty clean)

check the book if you can and let it enter your soul: https://de.wikipedia.org/wiki/Clean_Code

참고URL : https://stackoverflow.com/questions/31548311/angular-html-binding

반응형