My problem is the following, I get as a response from a service an entire HTML page that I should display back t the user. Now this is an issue for Angular since it thinks I might be a victim of cross site scripting if I do that. The source I get the HTML from is trusted so I wanted to white list it or bypass the sanitizer in some way and render the view to the user.
The problem I ran into is that the file I get also contains 'style' and 'script' tags for manipulating the dom, and no matter how I place the bypass function calls something gets caught and the entire thing doesn't render properly. Is there any way I could maybe separate the HTML file clear it and then put it back together or something else?
Try this:
import { DomSanitizer } from '#angular/platform-browser';
constructor(private sanitizer: DomSanitizer) { }
//where you want to use the unsafe html
const sanitizedHtml = this.sanitizer.bypassSecurityTrustResourceUrl(html);
What you can do, but goes against the Angular principle, is to append the html markup to the innerhtml of your component or the DOM using ElementRef from
#angular/core.
Sample appcomponent:
import { Component, ElementRef } from '#angular/core';
#Component({
selector: 'my-app',
template: ``,
})
export class AppComponent {
private htmlTemplate = `
<div>Loading template</div>
<script type="text/javascript">
console.log('loaded');
</script>
`;
constructor(private elementRef: ElementRef) { }
ngAfterViewInit() {
let elem: Element = this.elementRef.nativeElement;
elem.innerHTML = this.htmlTemplate;
}
}
Related
I am trying to add something to the constructor of one of my Angular components, however, anytime I put something in the constructor, it renders the entire page blank - getting rid of all of the other components and displaying just the background.
For example - this will work.
TS
#Component({
selector: 'app-cardboxes',
templateUrl: './cardboxes.component.html',
styleUrls: ['./cardboxes.component.scss']
})
export class CardboxesComponent implements OnInit {
constructor() { }
ngOnInit(): void {}
}
And this will render completely blank - removing everything, even the other components.
TS
#Component({
selector: 'app-cardboxes',
templateUrl: './cardboxes.component.html',
styleUrls: ['./cardboxes.component.scss']
})
export class CardboxesComponent implements OnInit {
constructor(private dialog: MatDialog) { }
ngOnInit(): void {}
}
For the record, it doesn't matter what is put in the constructor - it is the same result every time. The Chrome terminal says that there is a NullInjectorError - No provider for MatDialog
Is there a reason for this, or an easy solution? I do not understand why this is happening and I really need to be able to use the constructors. Do I have to make another import somewhere? Is there a configuration I am missing?
You are trying to use angular materials. Please use this comand in console.
npm i #angular/material
Open app.module and
NgModule ({....
imports: [...,
MatSliderModule,
…]
Items adsed in constructor should be imported in module
I need to put a loading in multiple components of my project. So instead of putting the same HTML over and over again across the components, I need to know what's the best way to not repeat code, but I don't know if this is correct thing to do. I have created a component called loading-graphic, which I bind it in every HTML file of the respective components. I read about ngTemplateOutlet and ngContent, but to be honest it doesn't make sense in my head to use it for this case (and I don't get it too... I'm a beginner on it). So, on what should I bet? Thanks.
Base on your question, I think creating Reusable Components with NgTemplateOutlet would be the best solution to avoid repeating HTML in different component Templates. It allows you to pass parameters base on your host component and makes your Angular app easier to test and develop since it sllows easily modified reusable component for various use cases without having to modify individual components itself.
Since you are a begginer I am going to Illustrate simple way of using NgTemplateOutlet, however dive deep later on Templates and Stamps.
Imaging you have a reusable Search component where you want to hide a check box base on the parent component. Your Template will look like below.
we pass data from the parent component to the child/Search component using #Input and property binding, so we define which checkboxes to hide base on Parent component.
here is the code sample for Search Component
search.component.ts
======================
import { Component, OnInit, Output, EventEmitter, Input } from '#angular/core';
#Component({
selector: 'app-search',
templateUrl: './app-search.component.html',
styleUrls: ['./app-search.component.css']
})
export class AppSearchComponent implements OnInit {
accountName: string = '';
#Output() accountSearchChange = new EventEmitter<string>(); //1. Event Binding to pass data from Child to Parent Component ->Int
#Input() searchMode: 'account' | 'holder' | 'distribution' = 'account'; //Use NgTemplateOutlet for reusable componenet
constructor() { }
ngOnInit() {
}
//2. Event Binding to pass data from Child to Parent Component ->Invoke Emit
doSearchFilter(searchText: string) {
console.log('Search Child: doSearchFilter -> ' + searchText);
this.accountSearchChange.emit(searchText);
}
clearFilters() {
console.log('Account Search: Clear Filter is called');
this.accountName = '';
}
}
search.component.html
=====================
<ng-container [ngSwitch]="searchMode">
<div class="input-full-width" *ngSwitchCase="'account'">
<mat-checkbox class="example-container check-full-width">Show active and pending only</mat-checkbox>
</div>
<div class="input-full-width" *ngSwitchCase="'holder'">
<mat-checkbox class="example-container check-full-width">View only holders with missing requirements</mat-checkbox>
</div>
<div class="input-full-width" *ngSwitchCase="'holder'">
<mat-checkbox class="example-container check-full-width">View only active Holders</mat-checkbox>
</div>
</ng-container>
I am using Search component inside Account component and below is the code sample.
in HTML file i am referring app-search css selector and pass the search Mode defined in ts.
import { Component, OnInit, ViewChild, AfterViewInit } from '#angular/core';
import { MatSort, MatTableDataSource, MatPaginator } from '#angular/material';
import { Router } from "#angular/router";
import { Observable } from 'rxjs';
import { AccountService } from 'src/app/core/services/account.service';
import { Deal } from 'src/app/core/models/deal';
#Component({
selector: 'app-account',
templateUrl: './account.component.html',
styleUrls: ['./account.component.css']
})
export class AccountsComponent implements OnInit, AfterViewInit {
displayedColumns: string[] = ['accountId', 'accountShortName', 'accountType'];
public dealDataSource = new MatTableDataSource<Deal>();
dealsObservable: Observable<Deal[]>;
searchMode = 'distribution';
isLoadingResults = true;
#ViewChild(MatSort) sort: MatSort;
#ViewChild(MatPaginator) paginator: MatPaginator;
constructor(private router: Router, private api: AccountService) { }
......................................................
<app-search (accountSearchChange)='doFilter($event)' [searchMode]="searchMode"></app-search>
Hope this is clear.
i think loading component is not a bad Idee. Use loading component in your app-root component. You can use a loading.service and interceptor to display or hide the component. You will get automatically a Loading Indicator for each API call.
sample: https://medium.com/#zeljkoradic/loader-bar-on-every-http-request-in-angular-6-60d8572a21a9
I am using angular 6. I have a dynamically created HTML file. Which may have errors like:
self closing tags
closing tags missing
mathematical equations
custom attributes
errors like Template parse errors:
There is no directive with "exportAs" set to "aff" (
Is there any way to skip all errors and simply load HTML content in angular?
Try like this. I haven't test this code.
import { Pipe, PipeTransform } from '#angular/core';
import { DomSanitizer } from '#angular/platform-browser';
#Pipe({ name: 'keepHtml', pure: false })
export class EscapeHtmlPipe implements PipeTransform {
constructor(private sanitizer: DomSanitizer) {
}
transform(content) {
return this.sanitizer.bypassSecurityTrustHtml(content);
}
}
Ref link
I would first encourage to use nglint in your code .
From my viewpoint, it is a very bad idea to generate HTML from angular, and I seriously think it will not work at all ! That's is angular job. You have to generate dynamic components . Then, angular will render these components in html.
Use an html validator after generating the html page, that will permit to fix it.
I want to load the external jsp page content as template in my component in angular 6 application.
#Component({
selector: 'app-conrequest',
templateUrl:'mydomain.com:port/utils/registerUser.jsp',
styleUrls: ['./conrequest.component.css']
})
In the above code, I have mentioned the jsp page url, which I want to load as a template.
Please help me on this.
Thanks,
Suresh
First of all whichever external link you are using it should "return" something.
If there is no information in return it will always gives you an error.
Lets begin your answer...
Step 1- First you need to import HttpClient and Map
import { HttpClient } from '#angular/common/http';
import 'rxjs/add/operator/map';
Step 2- and your #Component decorator should look like this
#Component({
selector: 'my-template',
template: `<div [innerHtml]="myTemplate">
</div> `})
Step 3- in your class you can import your external template like...
export class TestComponent {
private myTemplate: any = '';
constructor(http: HttpClient) {
http.get('www.abc.com/index.html', {responseType: 'text'}).subscribe(data => this.myTemplate = data);
}
}
Step 4 - Also import httpClient in RootModule
imports: [
...
...
HttpClientModule
],
That's it. Try with yours.
Thanks
Sunil Sain
Styles like
<div [style.background-image]="\'url(\' + image + \')\'">Background</div>
<div [style.transform]="rotate(7deg)"
are not added anymore
update (2.0.0 final)
import { Pipe, PipeTransform } from '#angular/core';
import { DomSanitizer } from '#angular/platform-browser';
#Pipe({name: 'safeHtml'})
export class SafeHtml implements PipeTransform {
constructor(private sanitizer:DomSanitizer){}
transform(html) {
return this.sanitizer.bypassSecurityTrustStyle(html);
// return this.sanitizer.bypassSecurityTrustHtml(html);
// return this.sanitizer.bypassSecurityTrustScript(html);
// return this.sanitizer.bypassSecurityTrustUrl(html);
// return this.sanitizer.bypassSecurityTrustResourceUrl(html);
}
}
See also https://angular.io/api/platform-browser/DomSanitizer
<div [innerHTML]="someHtml | safeHtml"
update
DomSanitizationService is going to be renamed to DomSanitizer in RC.6
original
This should be fixed in RC.2
See also Angular2 Developer Guide - Security
Angular2 intruduced sanitization of CSS values and property binding like [innerHTML]=... and [src]="..." in RC.1
See also https://github.com/angular/angular/issues/8491#issuecomment-217467582
The values can be marked as trusted by using DomSanitizer.bypassSecurityTrustStyle(...)
import {DomSanitizer} from '#angular/platform-browser';
...
constructor(sanitizer: DomSanitizationService) {
this.backgroundImageStyle = sanitizer.bypassSecurityTrustStyle('url(' + this.image + ')');
// for HTML
// this.backgroundImageStyle = sanitizer.bypassSecurityTrustHtml(...);
}
and binding to this value instead the untrusted plain string.
This can also be wrapped in a pipe like
#Pipe({name: 'safeStyle'})
export class Safe {
constructor(private sanitizer:Sanitizer){}
transform(style) {
return this.sanitizer.bypassSecurityTrustStyle(style);
// return this.sanitizer.bypassSecurityTrustHtml(style);
// return this.sanitizer.bypassSecurityTrustScript(value);
// return this.sanitizer.bypassSecurityTrustUrl(value);
// return this.sanitizer.bypassSecurityTrustResourceUrl(value);
}
}
<div [ngStyle]="someStyle | safeStyle"></div>
with
someHtml = `click to see the awesome`;
is still working though :-[ (it's work in progress)
Plunker example (Angular 2.0.0-rc-1)
See also Angular 2 Security Tracking Issue
and https://angular.io/docs/ts/latest/api/platform-browser/index/DomSanitizer-class.html
Hint about {{...}}
Sanitized content can't be bound using prop="{{sanitizedContent}}" because {{}} stringyfies the value before it is assigned which breaks sanitization.
Bypassing sanitizer to trust any content can be a security concern. Since Angular is not a dedicated sanitizing library, it is overzealous towards suspicious content to not take any risks. It removes almost all attributes, for example. You can delegate sanitizing to a dedicated library — DOMPurify. Here's a wrapper library I've made to easily use DOMPurify with Angular.
https://github.com/TinkoffCreditSystems/ng-dompurify
It also has a pipe to declaratively sanitize HTML:
<div [innerHtml]="value | dompurify"></div>
One thing to keep in mind is DOMPurify is great for sanitizing HTML/SVG, but not CSS. So you can provider Angular's CSS sanitizer to handle CSS:
import {NgModule, ɵ_sanitizeStyle} from '#angular/core';
import {SANITIZE_STYLE} from '#tinkoff/ng-dompurify';
#NgModule({
// ...
providers: [
{
provide: SANITIZE_STYLE,
useValue: ɵ_sanitizeStyle,
},
],
// ...
})
export class AppModule {}
It's internal — hense ɵ prefix, but this is how Angular team use it across their own packages as well anyway.