Ответ 1
Правильный синтаксис следующий:
<div [innerHTML]="theHtmlString"></div>
Работает на 8.2.11
Я пишу приложение Angular, и у меня есть ответ HTML, который я хочу отобразить.
Как я могу это сделать? Если я просто использую синтаксис привязки {{myVal}}
он кодирует все символы HTML (конечно).
Мне нужно как-то привязать innerHTML
div
к значению переменной.
Правильный синтаксис следующий:
<div [innerHTML]="theHtmlString"></div>
Работает на 8.2.11
Angular 2.0.0 и Angular 4.0.0 final
Для безопасного контента просто
<div [innerHTML]="myVal"></div>
DOMSanitizer
Потенциальный небезопасный HTML должен быть явно помечен как надежный, используя дезинфицирующее средство 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 некоторые стили не могут быть добавлены с использованием синтаксиса привязки
И docs: https://angular.io/api/platform-browser/DomSanitizer
Предупреждение о безопасности
Доверенный пользовательский HTML-код может представлять угрозу безопасности. Ранее упомянутые документы:
Вызов любого из API
bypassSecurityTrust...
отключает встроенную санитацию Angular для переданного значения. Внимательно проверяйте и проверяйте все значения и пути кода, входящие в этот вызов. Удостоверьтесь, что для этого контекста безопасности пользовательские данные соответствующим образом экранированы. Подробнее см. В Руководство по безопасности.
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.
Чтобы добавить HTML, содержащий Angular -специфическую разметку (привязка свойств или значений, компоненты, директивы, трубы,...), необходимо добавить динамический модуль и компилировать компоненты во время выполнения. Этот ответ дает более подробную информацию Как я могу использовать/создавать динамический шаблон для компиляции динамического компонента с Angular 2.0?
[innerHtml]
- отличный вариант в большинстве случаев, но он терпит неудачу с действительно большими строками или когда вам нужен жестко закодированный стиль в html.
Я хотел бы поделиться другим подходом:
Все, что вам нужно сделать, это создать div в вашем html файле и дать ему некоторый 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.
Это просто способ, которым вы это сделаете, используя собственный javascript, но в среде Angular. Я не рекомендую это, потому что делает код более беспорядочным, но иногда нет другого варианта.
См. также Angular 2 - innerHTML стиль
Привязка Html не будет работать при использовании {{interpolation}}
, вместо этого используйте "Выражение":
недействительным
<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?
Использование [innerHTML] напрямую без использования Angular Дезинфицирующее средство DOM не является вариантом, если оно содержит созданный пользователем контент. Трубка safeHtml, предложенная @GünterZöchbauer в его ответе, является одним из способов дезинфекции контента. Следующая директива - другая:
import { Directive, ElementRef, Input, OnChanges, Sanitizer, SecurityContext,
SimpleChanges } from '@angular/core';
// Sets the element 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: Вставка HTML с сервера в DOM с помощью angular2 (общая манипуляция DOM в Angular2), "inner-html" эквивалентно "ng-bind-html" в Angular 1.X
Чтобы сделать полный ответ, если ваше содержимое html находится в переменной компонента, вы также можете использовать:
<div [innerHTML]=componementVariableThatHasTheHtml></div>
Приносим извинения, если я пропущу здесь пункт, но я хотел бы рекомендовать другой подход:
Я думаю, что лучше вернуть необработанные данные из вашего приложения на стороне сервера и привязать его к шаблону на стороне клиента. Это приводит к более проворным запросам, поскольку вы только возвращаете json с вашего сервера.
Мне кажется, что имеет смысл использовать Angular, если все, что вы делаете, - это выборка html с сервера и ее ввод "как есть" в DOM.
Я знаю Angular 1.x имеет привязку html, но я еще не видел аналога в Angular 2.0. Они могут добавить это позже. Во всяком случае, я бы все же рассмотрел данные api для вашего приложения Angular 2.0.
У меня есть несколько примеров здесь с некоторой простой привязкой данных, если вам интересно: http://www.syntaxsuccess.com/viewarticle/angular-2.0-examples
Просто используйте атрибут [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 полезно!
В Angular 2 вы можете сделать 3 типа привязок:
[property]="expression"
→ Любое свойство html может ссылаться на
выражение. В этом случае, если свойство изменения выражений будет обновляться,
но это не работает по-другому.(event)="expression"
→ Когда событие активирует выражение выполнения.[(ngModel)]="property"
→ Привязывает свойство от js (или ts) к html. Любое обновление этого свойства будет заметно повсеместно.Выражение может быть значением, атрибутом или методом. Например: '4', 'controller.var', 'getValue()'
Пример здесь
Мы всегда можем передать html-контент в свойство innerHTML
чтобы отобразить html-динамический контент, но этот динамический html-контент также может быть зараженным или вредоносным. Поэтому, прежде чем передавать динамический контент в innerHTML
мы всегда должны убедиться, что контент DOMSanitizer
(с помощью 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>
Работа в AngularJS v2.1.1
<div [innerHTML]="variable or htmlString">
</div>
Способ динамического добавления элементов в 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
Вы можете использовать несколько подходов для достижения решения. Как уже сказано в утвержденном ответе, вы можете использовать:
<div [innerHTML]="myVal"></div>
в зависимости от того, чего вы пытаетесь достичь, вы также можете попробовать другие вещи, такие как JavaScript DOM (не рекомендуется, операции DOM медленные):
презентация
<div id="test"></test>
Составная часть
var p = document.getElementsById("test");
p.outerHTML = myVal;
Если вы хотите это в Angular 2 или Angular 4, а также хотите сохранить встроенный CSS, тогда вы можете использовать
<div [innerHTML]="theHtmlString | keepHtml"></div>
Вы можете использовать этот метод
<div [innerHTML]=var></div>
или привязать его по id
<div #html></div>
и в компоненте
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;
}
}
Вы можете применить несколько каналов для стиля, ссылки и HTML следующим образом в .html
<div [innerHTML]="announcementContent | safeUrl| safeHtml">
</div>
и в .ts pipe для дезинфицирующего средства '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'
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);
}
}
это будет применяться как без нарушения какого-либо стиля, так и события щелчка ссылки
Я собрал видеоответ, чтобы объяснить, как использовать привязку свойства выражения вместо фигурных скобок интерполяции. Вы можете видеть, как фигурные скобки компилируют только строки. Поэтому, если вы хотите иметь код или сущность HTML, вам нужно использовать выражение свойства. Короткое видео покажет вам, как.
попробуйте этот код
ваша строка с тегом html, как показано ниже
htmlString:string = "Hello<br/>Html"
вы можете получить строку на странице html
<ion-content>
<ion-item>
<div [innerHTML] = "'<p>' + htmlString + '</p>'"></div>
</ion-item>
</ion-content>
Если у вас есть шаблоны в вашем приложении angular (или любом другом), и вы возвращаете HTML-шаблоны из вашего бэкэнд через HTTP-запрос/ответ, вы смешиваете шаблоны между интерфейсом и бэкэнд.
Почему бы просто оставить шаблонный материал ни в интерфейсе (я бы это предложил), ни в бэкэнде (довольно непрозрачный imo)?
И если вы храните шаблоны во внешнем интерфейсе, почему бы просто не ответить JSON на запросы на бэкэнд. Вам даже не нужно внедрять структуру RESTful, но сохранение шаблонов с одной стороны делает ваш код более прозрачным.
Это окупится, когда кто-то другой справится с вашим кодом (или даже вы сами повторно запустите свой собственный код через некоторое время)!
Если вы все сделаете правильно, у вас будут небольшие компоненты с небольшими шаблонами, и, самое главное, если ваш код будет imba, тот, кто не знает языки кодирования, сможет понять ваши шаблоны и вашу логику! Таким образом, добавьте свои функции/методы как можно малые. В конечном итоге вы узнаете, что поддержка, рефакторинг, просмотр и добавление функций будет намного проще по сравнению с большими функциями/методами/классами и смешением шаблонов и логики между интерфейсом и бэкэнд - и сохранить как можно больше логики в бэкэнд если ваш интерфейс должен быть более гибким (например, написание интерфейса Android или переход на другой интерфейс).
Философия, человек:)
p.s.: вам не нужно реализовывать 100% чистый код, потому что это очень дорого - особенно если вам нужно мотивировать членов команды;) но: вы должны найти хороший баланс между подходом к более чистому коду и тем, что у вас есть (может быть, оно уже довольно чистое)
проверьте книгу, если сможете, и пусть она войдет в вашу душу: https://de.wikipedia.org/wiki/Clean_Code
Ниже приведен код, который поможет вам
myval вы можете заменить нужным html
<div [innerHTML]="myVal"></div>
Чтобы связать внутренний HTML любого элемента HTML с переменным значением, которое вы можете использовать:
ng-bind-html
Директива и передать ей переменную или выражение (используя переменные, литералы и операторы).Попробуйте здесь: JSFiddle
<div ng-app="myApp" ng-controller="myCtrl">
<p ng-bind-html="myText"></p>
<p>My name is <span ng-bind-html="name"></span><p>
<p> Position:<span ng-bind-html="position"></span></p>
</div>
<script>
var app = angular.module("myApp", ['ngSanitize']);
app.controller("myCtrl", function($scope) {
$scope.myText = "<h1>Leaderboard</h1><hr width='80%' size='5' color='#000000'>";
$scope.name = "<h2>Jane Doe</h2>";
$scope.position = "<h1>1<sup>st</sup><h1>";
});
</script>
Примечание: В этом примере содержится "angular -sanitize.js", который имеет функции для удаления потенциально опасных токенов из HTML.
ng-html-compile
Директива, используемая для связывания и компиляции фрагмента HTML'Если вы используете ng-html-компиляцию внутри директивы, которая создает дочернюю область (например, ng-repeat), используйте объект для определения вашей модели. В противном случае привязка будет создана с новым свойством, созданным внутри области содержимого. '- Francis Bouvier
index.html
<html ng-app="MyApp">
<body ng-controller="HomeCtrl">
<div ng-repeat="htmlTemplate in htmlTemplates">
<span ng-html-compile="htmlTemplate"></span>
</div>
<div>{{author.name}}</div>
<script src="libs/angular.js"></script>
<script src="libs/ngHtmlCompile.js"></script>
<script src="script.js"></script>
</body>
</html>
script.js
var myApp = angular.module('MyApp', ['ngHtmlCompile']);
function HomeCtrl($scope) {
$scope.author = {
name: 'Camaron de la Isla'
};
$scope.htmlTemplates = ['<b>Name</b> <input type="text" ng-model="author.name" />'];
};
ngHtmlComile.js
angular.module('ngHtmlCompile', []).
directive('ngHtmlCompile', function($compile) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
scope.$watch(attrs.ngHtmlCompile, function(newValue, oldValue) {
element.html(newValue);
$compile(element.contents())(scope);
});
}
}
});
Источники: