Using Angular 5 and Firebase, I have created a review website that allows users to create reviews on the CreateComponent and read them on the ReviewComponent. I'd like the body of the review to be able to contain HTML for links or images.
The ReviewComponent pulls the body of the review with:
<p style="margin-bottom: 2rem; white-space: pre-wrap;">{{review.body}}</p>
I am using pre-wrap to maintain the body's line breaks.
An example input from the CreateComponent would be:
I already can’t wait to see what comes next.
When I inspect the output of the body I see this:
<p _ngcontent-c1 style="margin-bottom: 2rem; white-space: pre-wrap;">I already can’t wait to see <a href="http://www.ign.com/articles/2017/11/30/marvels-the-avengers-infinity-war-trailer-breakdown">what comes next.</a></p>.
How can I change the HTML to enable the string to work correctly with links and images?
Binding review.body to [innerHTML] corrected this.
<p style="margin-bottom: 2rem; white-space: pre-wrap;">{{review.body}}</p>
is now
<p style="margin-bottom: 2rem; white-space: pre-wrap;" [innerHTML]="review.body"></p>
Here is solutions for your issue:
https://plnkr.co/edit/VHvVpvnTeoGWsA0d3eex?p=preview
Here is code:
//our root app component
import {Component, NgModule, VERSION, Pipe, PipeTransform, ChangeDetectorRef } from '#angular/core'
import {BrowserModule} from '#angular/platform-browser'
import { FormsModule } from '#angular/forms';
#Component({
selector: 'my-app',
template: `
<div [outerHTML]='selectedValue | html'></div>
`,
})
export class App {
selectedValue: string = 'I already can’t wait to see what comes next.';
constructor(private cd: ChangeDetectorRef) {
}
}
#Pipe({
name: 'html'
})
export class HtmlPipe implements PipeTransform {
transform(value: string) {
return `<div>${value}</div>`;
}
}
#NgModule({
imports: [ BrowserModule, FormsModule ],
declarations: [ App, HtmlPipe ],
bootstrap: [ App ]
})
export class AppModule {}
You could write pipe for this application, like in this article:
How to allow html in return of angular2 pipe?
Related
this is my html component file allData has data from db with inline style
<div class="col-12" *ngFor="let data of allData">
<div [innerHTML]="data.description"></div>
</div>
You need to bypass the Angular protection using DomSanitizer. DomSanitizer, a service of Angular helps to prevent attackers from injecting malicious client-side scripts into web pages.
<div class="col-12" *ngFor="let data of allData">
<div [innerHTML]="getData(data.description)"></div>
</div>
in your .ts file
constructor(protected sanitizer: DomSanitizer) {}
getData(description) {
return this.sanitizer.bypassSecurityTrustHtml(description);
}
Working demo: https://stackblitz.com/edit/angular-xeuupi-ulwvem?file=src%2Fapp%2Flist-overview-example.ts
do not forget to sanitize the received data, You can use the following pipe to sanitize your data :
import { DomSanitizer } from '#angular/platform-browser'
import { PipeTransform, Pipe } from "#angular/core";
#Pipe({ name: 'safeHtml'})
export class SafeHtmlPipe implements PipeTransform {
constructor(private sanitized: DomSanitizer) {}
transform(content) {
return this.sanitized.bypassSecurityTrustHtml(content);
}
}
Then :
<div class="col-12" *ngFor="let data of allData">
<div [innerHTML]="data.description | safeHtml"></div>
</div>
NOTE:
Add the SafeHtmlPipe pipe to the declarations section of your module
I want to make all <p> in the template have font-variant small-caps. Can I pass an html to ViewChildren? I have seen examples where template reference variables or components are passed but haven't seen an example where the selector passed to ViewChildren is an html tag or a css class.
template: `<p>
I am a static component
</p>
<p>
I am another para but I have an id (template reference variable) #pref. I got my blue color using ViewChild and Renderer2
</p>
<p>
All paragraphs are small-caps because using ViewChildren and Renderer2, the style was set to bold
</p>`
.ts file
import { Component,ViewChild, ViewChildren, QueryList,ElementRef,Renderer2,OnInit } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
name = 'Angular';
#ViewChildren("p") paraList:QueryList<any>; /*I SUPPOSE I CANT DO THIS AS P IS INTERPRETED AS TEMPLATE REFERENCE VARIABLE AND NOT <P>*/
constructor(private renderer:Renderer2){
}
ngAfterViewInit(){ //QueryList becomes available now
this.paraList.forEach(para =>{this.renderer.addClass(para,'boldClass')})
}
}
css
.boldClass{
font-variant: small-caps;
}
I have created a simple directive that works in an angular demo app according to the guide here.
The appHighlight directive works in Angular, but does nothing when applied in a new blank Ionic-v4 app.
Here are the steps I took to create this ionic project:
ionic start directiveTest blank --type=angular
ionic generate directive Highlight
imported ElementRef from ‘#angular/core’ and injected into
HighlightDirective constructor as shown below.
set ElementRef.nativeElement.style.backgroundColor = ‘yellow’ inside
the directive constructor
checked to make sure HighlightDirective was declared in
app.module.ts added ‘appHighlight’ to tag in home.page.html
Is this expected to work as shown, or am I missing something? Thanks!
highlight.directive.ts:
import { Directive, ElementRef } from '#angular/core';
#Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
constructor(el: ElementRef) {
el.nativeElement.style.backgroundColor = 'yellow';
}
}
app.module.ts:
#NgModule({
declarations: [AppComponent, HighlightDirective],
entryComponents: [],
imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule],
providers: [
StatusBar,
SplashScreen,
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
],
bootstrap: [AppComponent]
})
export class AppModule {}
home.page.html:
<ion-content padding>
The world is your oyster.
<p appHighlight> test </p>
</ion-content>
I have a contenteditable div that works great until I assign the changed text back into initial variable. When editing and I press enter, a new line appears properly in the editable div, but does not get stored into 'name'. The next character typed ends up at the end of the previous line, and the cursor goes to the beginning of the first line. If I remove the (input) line, the div behaves properly, but 'name' is not updated. How do I get the div to behave properly and update 'name'?
Plunk Demo
import {Component, NgModule} from '#angular/core'
import {BrowserModule} from '#angular/platform-browser'
#Component({
selector: 'my-app',
template: `
<div style="white-space: pre-wrap;"
[textContent]=name
(input)="name=$event.target.textContent"
contenteditable>
</div>
<div style="white-space: pre-wrap;">{{name}}</div>
`,
})
export class App {
name:string;
constructor() {
this.name = `TEST`
}
}
#NgModule({
imports: [ BrowserModule ],
declarations: [ App ],
bootstrap: [ App ]
})
export class AppModule {}
Expected Result:
Test
Test
Actual Result:
estTestT
With some little changes you can make it work.
Change textContent attribute to innerText.
Set the the innerText value value in ngOnInit and forgo ngModel.
Typescript:
#ViewChild('myEditable') private myEditable;
name:string;
constructor() {
this.name = 'I am editable';
}
ngOnInit(){
this.myEditable.nativeElement.innerText = this.name;
}
HTML:
<div #myEditable contentEditable (input)="name=$event.target.innerText"></div>
<div style="white-space:pre">{{name}}</div>
Demo
I can't work out why Angular will not allow me to reference my components selector. I have a page which when you click on a list item the page should bring up another templates html. This is my code.
The error I keep receiving is 'message-component' is not a known element:
1. If 'message-component' is an Angular component, then verify that it is part of this module.
2. If 'message-component' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '#NgModule.schemas' of this component to suppress this message.
Messages.component.html
<div id="Case" class="w3-container city" style="display:none">
<h2>Case</h2>
<message-case> </message-case>
</div>
I don't understand why it is giving me this error when the Message Component is declared and imported in both the NgModule and within the component.
Messages.Module.ts
#NgModule
({
imports: [SharedModule],
declarations: [
MessagesComponent,
MessageCaseComponent,
MessagesFilterPipe,
CreateMessageComponent,
],
})
Finally this is the file I am trying to display using the components selector
import { Component, OnInit } from '#angular/core';
import { IMessage } from './message';
import { ActivatedRoute, Router, Params } from '#angular/router';
import {MessagesComponent} from './messages.component';
import {CreateMessageComponent} from './createmessage.component';
#Component
({
moduleId: module.id,
selector: 'message-case',
templateUrl: 'message-case.html'
})
All help would be appreciated! I'm seemingly at a dead end right now.
Firstable the name file is wrong you putted this filename in the description
"Messages.component.html"
And the path of the template must contains "./" if it is in the same folder if it is in another folder you must put the relative path folder/file
#Component
({
moduleId: module.id,
selector: 'message-case',
templateUrl: './Messages.component.html'
})