Piszę aplikację Angular i mam odpowiedź HTML, którą chcę wyświetlić.
Jak mogę to zrobić? Jeśli po prostu użyję składni wiązania {{myVal}}
, koduje wszystkie znaki HTML (oczywiście).
Potrzebuję w jakiś sposób powiązać innerHTML
a div
ze zmienną.
Piszę aplikację Angular i mam odpowiedź HTML, którą chcę wyświetlić.
Jak mogę to zrobić? Jeśli po prostu użyję składni wiązania {{myVal}}
, koduje wszystkie znaki HTML (oczywiście).
Potrzebuję w jakiś sposób powiązać innerHTML
a div
ze zmienną.
Odpowiedzi:
Prawidłowa składnia jest następująca:
Dokumentacja referencyjna
źródło
Angular 2.0.0 i Angular 4.0.0 final
Tylko dla bezpiecznych treści
DOMSanitizer
Potencjalnie niebezpieczny kod HTML musi zostać wyraźnie oznaczony jako zaufany za pomocą sanitizera DOM Angulars, aby nie usuwał potencjalnie niebezpiecznych części treści
z rurką jak
Zobacz też W RC.1 niektórych stylów nie można dodać przy użyciu składni wiązania
I dokumenty: https://angular.io/api/platform-browser/DomSanitizer
Ostrzeżenie bezpieczeństwa
Ufanie dodanemu użytkownikowi HTML może stanowić zagrożenie bezpieczeństwa. Wcześniej wspomniane dokumenty stwierdzają:
Znaczniki kątowe
Coś jak
z
nie spowoduje, że Angular przetworzy coś specyficznego dla Angulara
foo
. Angular zastępuje znaczniki Angular w czasie kompilacji wygenerowanym kodem. Znaczniki dodane w czasie wykonywania nie będą przetwarzane przez Angular .Aby dodać HTML, który zawiera znaczniki właściwe dla Angulara (powiązanie właściwości lub wartości, komponenty, dyrektywy, potoki, ...) wymagane jest dodanie modułu dynamicznego i kompilacja komponentów w czasie wykonywania. Ta odpowiedź zawiera więcej szczegółów Jak mogę użyć / utworzyć szablon dynamiczny do skompilowania komponentu dynamicznego z Angular 2.0?
źródło
import { BrowserModule, DomSanitizer } from '@angular/platform-browser'
import { Pipe } from '@angular/core'
[innerHtml]
jest świetną opcją w większości przypadków, ale zawodzi przy naprawdę dużych ciągach lub gdy potrzebujesz stylizacji w formacie HTML.Chciałbym podzielić się innym podejściem:
Wszystko, co musisz zrobić, to utworzyć div w pliku html i podać mu identyfikator:
Następnie w komponencie Angular 2 utwórz odwołanie do tego obiektu (tutaj TypeScript):
Następnie po prostu użyj
loadData
funkcji, aby dodać tekst do elementu HTML.Jest to tylko sposób na zrobienie tego przy użyciu natywnego języka JavaScript, ale w środowisku Angular. Nie polecam tego, ponieważ sprawia, że kod jest bardziej niechlujny, ale czasami nie ma innej opcji.
Zobacz także Angular 2 - stylizacja innerHTML
źródło
nativeElement
bezpośredni dostęp do właściwości, co jest uważane za złą praktykę. Jestem pewien, że[innerHTML]="..."
robi to samo pod maską, ale w dobry sposób Angular2.[innerHTML]
dużymi łańcuchami w Angular2?[innerHtml]
usuwa stylizację zakodowaną w HTML. W celu zintegrowania edytora wysiwyg musiałem zastosować wymienione tutaj podejście.[innerHTML]
podejście nie.Na [email protected]:
Wiązanie HTML nie będzie działać podczas używania
{{interpolation}}
, zamiast tego użyj „Wyrażenia”:nieważny
-> zgłasza błąd (interpolacja zamiast oczekiwanego wyrażenia)
poprawny
-> to jest właściwy sposób.
możesz dodać dodatkowe elementy do wyrażenia, takie jak:
Wskazówka
HTML dodany przy użyciu
[innerHTML]
(lub dodany dynamicznie za pomocą innych środków podobnychelement.appenChild()
lub podobnych) nie będzie przetwarzany przez Angular w jakikolwiek inny sposób niż dezynfekcja ze względów bezpieczeństwa.Takie rzeczy działają tylko wtedy, gdy HTML jest dodawany statycznie do szablonu komponentów. Jeśli potrzebujesz, możesz utworzyć komponent w czasie wykonywania, jak wyjaśniono w Jak używać / tworzyć dynamiczny szablon do kompilacji dynamicznego komponentu z Angular 2.0?
źródło
Bezpośrednie korzystanie z [innerHTML] bez użycia sanitizera DOM Angulara nie jest możliwe, jeśli zawiera treści tworzone przez użytkowników. Rura SafeHtml zasugerowana przez @ GünterZöchbauer w swojej odpowiedzi jest jednym ze sposobów odkażania zawartości. Następująca dyrektywa to kolejna:
Być stosowane
źródło
Can't bind to 'safeHtml' since it isn't a known property of 'div'.
ng-wersja 2.4.4constructor( private sanitizer: Sanitizer) {}
i powiązać wynik z tym, czego potrzebujesz, również użycie ElementRef jest zdecydowanie nie sugerowane.To działa dla mnie:
<div innerHTML = "{{ myVal }}"></div>
(Angular2, Alpha 33)Zgodnie z innym SO: Wstawianie HTML z serwera do DOM za pomocą angular2 (ogólna manipulacja DOM w Angular2) , „wewnętrzna-HTML” jest równoważna „ng-bind-HTML” w Angular 1.X
źródło
Aby uzyskać pełną odpowiedź, jeśli zawartość HTML jest w zmiennej składowej, możesz również użyć:
źródło
Przepraszam, jeśli nie rozumiem tego tutaj, ale chciałbym polecić inne podejście:
Myślę, że lepiej jest zwrócić surowe dane z aplikacji po stronie serwera i powiązać je z szablonem po stronie klienta. To sprawia, że żądania są bardziej zwinne, ponieważ zwracasz tylko json z serwera.
Dla mnie nie wydaje się sensowne korzystanie z Angulara, jeśli wszystko, co robisz, to pobieranie html z serwera i wstrzykiwanie go „tak, jak jest” do DOM.
Wiem, że Angular 1.x ma powiązanie HTML, ale nie widziałem jeszcze odpowiednika w Angular 2.0. Mogą jednak dodać to później. W każdym razie nadal rozważałbym API danych dla aplikacji Angular 2.0.
Mam tutaj kilka próbek z prostym powiązaniem danych, jeśli jesteś zainteresowany: http://www.syntaxsuccess.com/viewarticle/angular-2.0-examples
źródło
Podano już krótką odpowiedź: użyj
<div [innerHTML]="yourHtml">
wiązania.Jednak pozostałe wymienione tu porady mogą wprowadzać w błąd. Angular ma wbudowany mechanizm dezynfekujący, gdy łączysz się z takimi właściwościami. Ponieważ Angular nie jest dedykowaną biblioteką odkażającą, nadgorliwe jest podejrzane treści, aby nie ryzykować. Na przykład dezynfekuje całą zawartość SVG do pustego ciągu.
Możesz usłyszeć porady dotyczące „dezynfekcji” treści za pomocą
DomSanitizer
oznaczania zawartościbypassSecurityTrustXXX
metodami jako bezpiecznymi . Istnieją również sugestie, aby użyć do tego rurki i ta rurka jest często nazywanasafeHtml
.Wszystko to jest mylące, ponieważ faktycznie omija odkażanie , a nie odkażanie treści. Może to budzić obawy związane z bezpieczeństwem, ponieważ jeśli kiedykolwiek zrobisz to na treściach dostarczonych przez użytkownika lub na czymkolwiek, czego nie jesteś pewien - narażasz się na ataki złośliwego kodu.
Jeśli Angular usunie coś, czego potrzebujesz, dzięki wbudowanemu odkażaniu - zamiast wyłączania możesz to zrobić, to deleguj rzeczywistą dezynfekcję do dedykowanej biblioteki, która jest dobra w tym zadaniu. Na przykład - DOMPurify.
Zrobiłem dla niego bibliotekę opakowań, aby można ją było łatwo używać z Angularem: https://github.com/TinkoffCreditSystems/ng-dompurify
Ma także potok do deklaratywnej dezynfekcji HTML:
Różnica w stosunku do rur sugerowanych tutaj polega na tym, że faktycznie wykonuje dezynfekcję za pośrednictwem DOMPurify i dlatego działa dla SVG.
Należy pamiętać, że DOMPurify doskonale nadaje się do odkażania HTML / SVG, ale nie CSS. Możesz więc zapewnić odkażacz CSS Angulara do obsługi CSS:
To wewnętrzny - hense
ɵ
prefiks, ale i tak zespół Angular używa go w swoich pakietach. Ta biblioteka działa również dla Angular Universal i środowiska redredredingu po stronie serwera.źródło
Wystarczy użyć
[innerHTML]
atrybutu w kodzie HTML , coś takiego poniżej:Korzystanie
{{myVal}}
NIE działa zgodnie z oczekiwaniami! To nie będzie odebrać tagów HTML, takich jak<p>
,<strong>
etc i przekazać go wyłącznie jako ciągi ...Wyobraź sobie, że masz ten kod w swoim komponencie:
const myVal:string ='<strong>Stackoverflow</strong> is <em>helpful!</em>'
Jeśli użyjesz
{{myVal}}
, zobaczysz to w widoku:ale użycie
[innerHTML]="myVal"
powoduje oczekiwany wynik:Stackoverflow jest pomocny!
źródło
Możesz zastosować wiele potoków dla stylu, linku i HTML w następujący sposób w .html
oraz w rurze .ts dla sanitizera „URL”
potok do dezynfekatora „HTML”
będzie to miało zastosowanie zarówno bez zakłócania jakiegokolwiek stylu, jak i zdarzenia kliknięcia linku
źródło
InnerHTML jest właściwością elementów HTML, który pozwala ustawić to html-content programowo. Istnieje również właściwość innerText, która definiuje treść jako zwykły tekst.
[attributeName]="value"
Wspornik skrzynka otaczająca atrybut definiuje kątowym wejście wiążące. Oznacza to, że wartość właściwości (w twoim przypadku innerHtml) jest powiązana z danym wyrażeniem, gdy zmienia się wynik wyrażenia, zmienia się również wartość właściwości.Zasadniczo
[innerHtml]
pozwala więc na wiązanie i dynamiczną zmianę treści HTML danego elementu HTML.źródło
W Angular 2 możesz wykonać 3 rodzaje powiązań:
[property]="expression"
-> Każda właściwość HTML może zawierać link dowyrażenia. W takim przypadku właściwość zmieni wyrażenie zostanie zaktualizowana, ale nie działa to w drugą stronę.
(event)="expression"
-> Gdy zdarzenie aktywuje wykonanie wyrażenia.[(ngModel)]="property"
-> Wiąże właściwość z js (lub ts) do html. Wszelkie aktualizacje tej właściwości będą widoczne wszędzie.Wyrażenie może być wartością, atrybutem lub metodą. Na przykład: „4”, „controller.var”, „getValue ()”
Przykład tutaj
źródło
Sposób dynamicznego dodawania elementów do DOM, jak wyjaśniono w Angular 2 doc, polega na użyciu klasy ViewContainerRef z @ Angular / core.
Musisz zadeklarować dyrektywę, która zaimplementuje ViewContainerRef i będzie działać jako symbol zastępczy w twoim DOM.
Dyrektywa
Następnie w szablonie, w którym chcesz wstrzyknąć komponent:
HTML
Następnie z wstrzykniętego kodu komponentu wstrzykniesz komponent zawierający żądany kod HTML:
Dodałem w pełni działającą aplikację demonstracyjną do Angular 2, dynamicznie dodając komponent do wersji demo DOM
źródło
Możesz skorzystać z kilku podejść, aby osiągnąć rozwiązanie. Jak już powiedziano w zatwierdzonej odpowiedzi, możesz użyć:
w zależności od tego, co próbujesz osiągnąć, możesz także wypróbować inne rzeczy, takie jak javascript DOM (niezalecane, operacje DOM są powolne):
Prezentacja
Składnik
Wiązanie nieruchomości
JavaScript DOM Outer HTML
źródło
getElementsById
innej metody selekcji jest złe, ponieważ może przechwytywać elementy należące do zupełnie różnych komponentów, jeśli zawierają one elementy o tym samym identyfikatorze (lub innych kryteriach).Zawsze możemy przekazać
innerHTML
właściwość HTML do właściwości w celu renderowania dynamicznej treści HTML, ale ta dynamiczna treść HTML może być również zainfekowana lub złośliwa. Dlatego przed przekazaniem zawartości dynamicznejinnerHTML
zawsze powinniśmy upewnić się, że jest ona zdezynfekowana (używanaDOMSanitizer
), abyśmy mogli uciec od wszystkich złośliwych treści.Wypróbuj poniżej rury:
źródło
style: background-color
wszystkie rzeczy można rozebrać, dlatego najlepiej zacząć od początku, bo później bardzo się zdezorientujesz.Jeśli chcesz tego w Angular 2 lub Angular 4, a także chcesz zachować wbudowany CSS, możesz użyć
źródło
Możesz również powiązać właściwości klasy elementu kątowego z szablonem, używając formy kanonicznej, jak poniżej:
Dokumentacja kątowa: https://angular.io/guide/template-syntax#property-binding-property
Zobacz działający przykład stackblitz tutaj
źródło
Praca w Angular v2.1.1
źródło
<div _ngcontent-luf-0=""></div>
dla mnie.div
Jest pusty.Jeśli masz szablony w aplikacji kątowej (lub dowolnej innej ramie) i zwracasz szablony HTML z backendu za pomocą żądania / odpowiedzi HTTP, mieszasz szablony między frontendem a backendem.
Dlaczego nie zostawić szablonów w interfejsie (sugerowałbym to) lub w backendzie (całkiem nieprzejrzyste imo)?
A jeśli szablony są przechowywane w interfejsie użytkownika, dlaczego po prostu nie odpowiedzieć za pomocą JSON na żądania do zaplecza. Nie musisz nawet implementować struktury RESTful, ale trzymanie szablonów po jednej stronie czyni kod bardziej przejrzystym.
To się zwróci, gdy ktoś inny będzie musiał poradzić sobie z twoim kodem (lub nawet ty sam po pewnym czasie ponownie wprowadzasz swój kod)!
Jeśli zrobisz to dobrze, będziesz mieć małe komponenty z małymi szablonami, a co najważniejsze, jeśli twój kod to imba, ktoś, kto nie zna języków kodowania, będzie w stanie zrozumieć twoje szablony i logikę! Więc dodatkowo zachowaj swoje funkcje / metody tak małe, jak to tylko możliwe. W końcu dowiesz się, że utrzymanie, refaktoryzacja, przeglądanie i dodawanie funkcji będzie znacznie łatwiejsze w porównaniu do dużych funkcji / metod / klas oraz mieszanie szablonów i logiki między frontendem a backendem - i zachowaj tyle logiki w backendie jeśli twój frontend musi być bardziej elastyczny (np. pisanie frontendu dla Androida lub przełączanie się na inną strukturę frontendu).
Filozofia, człowiek :)
ps: nie musisz implementować w 100% czystego kodu, ponieważ jest on bardzo drogi - szczególnie jeśli musisz zmotywować członków zespołu;), ale: powinieneś znaleźć równowagę między podejściem do czystszego kodu a tym, co masz (może to jest już dość czysty)
sprawdź książkę, jeśli możesz i pozwól jej wejść do twojej duszy: https://de.wikipedia.org/wiki/Clean_Code
źródło