Angular2 include html from server into a div - html

I got a serie of html in my server. For example:
http://docs.example.com/intro.html
http://docs.example.com/page1.html
http://docs.example.com/page2.html
And I trying to include those files into a<div> in my angular2 v4 app. For example:
component.ts
public changePage(name: string) {
switch (name) {
case 'intro': this.myHtmlTemplate = 'http://docs.example.com/intro.html'; break;
case 'page1': this.myHtmlTemplate = 'http://docs.example.com/page1.html'; break;
case 'page2': this.myHtmlTemplate = 'http://docs.example.com/page2.html'; break;
}
}
component.html
<div [innerHtml]="myHtmlTemplate"></div>
but it doesnt work. I tried the following solutions:
Angular4 Load external html page in a div
Dynamically load HTML template in angular2
but it doesn't work for me. Can somebody help me with this problem please ?

Angular security Blocks dynamic rendering of HTML and other scripts. You need to bypass them using DOM Sanitizer.
Read more here : Angular Security
DO below changes in your code :
// in your component.ts file
//import this
import { DomSanitizer } from '#angular/platform-browser';
// in constructor create object
constructor(
...
private sanitizer: DomSanitizer
...
){
}
someMethod(){
const headers = new HttpHeaders({
'Content-Type': 'text/plain',
});
const request = this.http.get<string>('https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Your_first_HTML_form', {
headers: headers,
responseType: 'text'
}).subscribe(res => this.htmlString = res);
this.htmlData = this.sanitizer.bypassSecurityTrustHtml(this.htmlString); // this line bypasses angular security
}
and in HTML file ;
<!-- In Your html file-->
<div [innerHtml]="htmlData">
</div>
Here is the working example of your requirement :
Working Stackblitz Demo

This should do it:
First in your component.ts get the html with a http request:
import { Component, OnInit } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { map } from 'rxjs/operators'
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
constructor(private http: HttpClient) { }
htmlString: string;
ngOnInit() {
const headers = new HttpHeaders({
'Content-Type': 'text/plain',
});
const request = this.http.get<string>('https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Your_first_HTML_form', {
headers: headers,
responseType: 'text'
}).subscribe(res => this.htmlString = res);
}
}
And in your component.html simply use a one way data binding:
<div [innerHTML]="htmlString"></div>

You actually want to display a page inside your angular app right?
For that you can add a iframe tag:
<iframe width="400" height="600" [src]="myHtmlTemplate"></iframe>

you have to get HTTP call to load HTML in plain text and load in div using innerHtml.
export class AppComponent implements OnInit {
name = 'Kissht';
KisshtHtml;
constructor(
private http:HttpClient,
private sanitizer:DomSanitizer){ }
ngOnInit(){
this.http.get('https://kissht.com/',
{responseType:'text'}).subscribe(res=>{
this.KisshtHtml = this.sanitizer.bypassSecurityTrustHtml(res);
})
}
}
Sometime you might get CORS issue in stackblitz whil loading external Html
https://stackblitz.com/edit/display-external-html-into-angular

In your component first request pages with HTTP request
this.http.get('http://docs.example.com/intro.html').map(response => response.text()).subscribe(html => Your_template = html);
use innerhtml with the safehtml pipe so your inline styling will be applied
more info on GitHub page(https://gist.github.com/klihelp/4dcac910124409fa7bd20f230818c8d1)
<div [innerHtml]="Your_template | safeHtml"></div>

Related

Importing JSON from a server within Angular

I am reading data from a JSON, which is one a server and it updates regularly and changes. I need to be able to read this JSON from the server so that I display the most up to date information on my web page.
Currently, the to be able to read the JSONs they are stored within the same project folder as my angular project. (This was because they were not set up on the server when I started).
This is how I currently import the JSON to be able to read it:
import jsonInfo from '../../../info.json'
I thought I would be able to change the file link to the server address, like so:
import jsonInfo from 'http://servername/folder/info.json'
But, VSCode gives me an error: Cannot find module 'http://servername/folder/info.json'
This is definitely the location of the JSON I am trying to load because when I click the link it takes me to the JSON and displays it.
My question is, how do I import the JSON into my .ts from a server so that I can keep getting the updated information from the JSON?
JSON file on a server is just like any other web resource you would try to access (like an API endpoint, for example).
So you should use built in angular http client to access this JSON file.
For example:
import { HttpClient } from '#angular/common/http';
export class SomeService {
constructor(private http: HttpClient) { }
getInfo() {
return this.http.get('http://servername/folder/info.json');
}
}
//...
export class SomeComponent implements OnInit {
info: any;
constructor(private someService: SomeService) {}
ngOnInit() {
this.someService.getInfo().subscribe(info => this.info = info)
}
}
Use HttpClient get method.
this.httpClient.get('http://servername/folder/info.json').subscribe(data => {
// your logic
})
You can use HttpClient and do like as shown below
Working Demo
import { Component, OnInit } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
name = 'Angular';
data = [];
apiUrl = 'http://servername/folder/info.json';
GetData() {
this.http.get<any[]>(this.apiUrl)
.subscribe(data => {
this.data = data;
});
}
ClearData() {
this.data = [];
}
constructor(private http: HttpClient) {}
ngOnInit() {}
}

Angular, trouble using ngIf, async and Observable to wait until data is ready to display content

I am new to Angular and I am stuck. I can't seem to get this to work and I think I'm just making some mistakes on how I'm implementing the Observable. Currently I am using a local json file as my data source, but in my main project I will connect to an external API. I have stripped everything down to make it as basic as possible and still no luck.
Here's campaign.component.ts
import { Component, OnInit } from '#angular/core';
import { Observable } from 'rxjs';
import { CampaignService } from '../campaign.service';
#Component({
selector: 'app-campaign',
templateUrl: './campaign.component.html',
styleUrls: ['./campaign.component.css']
})
export class CampaignComponent implements OnInit {
$campaign: Observable<any>;
constructor(
private campaignService: CampaignService
) {}
ngOnInit(): void {
this.getCampaign();
}
getCampaign(): void {
this.campaignService.getCampaign().subscribe((data) => {
this.$campaign = data;
console.log(this.$campaign);
});
}
}
Here's the template html, campaign.component.html
<div *ngIf="($campaign | async) as campaign; else loading">
<!--this never loads-->
{{campaign.shortName}}
</div>
<ng-template #loading>
<!--this is all I see-->
Loading stuff in ngIf...
</ng-template>
<br>
<br>
<!--this works so I know the data loads and that my json file is formatted correctly-->
<p>Outside of ngIf works: {{$campaign.shortName}}</p>
Here's the service, campaign.service.ts
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders, HttpErrorResponse } from '#angular/common/http';
import { Observable, of } from 'rxjs';
import { map} from 'rxjs/operators';
const endpoint = 'assets/api.json';
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json'
})
};
#Injectable()
export class CampaignService {
constructor(private http: HttpClient) {}
private extractData(res: Response) {
let body = res;
return body || { };
}
getCampaign(): Observable<any> {
const url = endpoint;
console.log(url);
return this.http.get(url).pipe(
map(this.extractData));
}
}
Thanks for taking the time to help with this.
getCampaign(): void {
this.campaignService.getCampaign().subscribe((data) => {
this.$campaign = data;
console.log(this.$campaign);
});
}
The above assigns the data value to the property this.$campaign but you've declared that property to be an observable.
<div *ngIf="($campaign | async) as campaign; else loading">
<!--this never loads-->
{{campaign.shortName}}
</div>
$campaign is not an observable so the async pipe resolves to undefined. The condition is always false.
<!--this works so I know the data loads and that my json file is formatted correctly-->
<p>Outside of ngIf works: {{$campaign.shortName}}</p>
The above works because $campaign was assigned the data value.
<p>Outside of ngIf works: {{($campaign | async)?.shortName}}</p>
You should always use async in the template for observables.
You can simplify the component by assigning the observable in the constructor.
constructor(private campaignService: CampaignService) {
this.$campaign = campaignService.getCampaign();
}
Alternatively, you don't have to use async if you subscribe and assign the data.
<div *ngIf="campaign; else loading">
<!--this never loads-->
{{campaign.shortName}}
</div>
<p>Outside of ngIf works: {{campaign?.shortName}}</p>

http observable<any> - Angular 4

I need to display the data on html that I get from web service. I am able to see the data in a format that I want, but I can't display properly on html. I think -any- in http.get is the problem. I can read data in console without -any- but it works fine with . When it works with it, it still does not print in html properly. Can anyone provide advice on this?
html
<div>{{this.res}}</div>
app.component.ts
import { Component, OnInit } from '#angular/core';
//import { IMovie } from './movie';
import { AppService } from './app.service';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
res: any[] ;
errorMessage: string;
constructor(private _appService: AppService) { }
ngOnInit(): void { this.getData(); }
getData(): void {
this._appService.getData()
.subscribe(
(res: any []) => this.res = res,
(error: any) => this.errorMessage = <any>error);
}
}
app.service.ts :
Injectable()
export class AppService {
private urlNorth = '';
constructor(private http: HttpClient) { }
getData(): Observable<any> {
const headers = new HttpHeaders();
headers.set('Content-Type', 'text/sml');
headers.set('Accept', 'text/xml');
headers.set('Content-Type', 'text/xml');
return this.http.get<any>(this.urlNorth,{responseType:'text', headers: headers})
.do(data => {
// console.log(data)
var dataParsed = data.replace('<string xmlns="service">', '').replace('</string>', '').replace(/</g, '<').replace(/>/g, '>');
// console.log(dataParsed);
parseString(dataParsed, (err, res) => {
if (err) {
return console.dir('invalid XML');
}
else {
console.log(res);
console.log(res.NewDataSet.Table[0].DataPointName[0]);
}
})
})
.catch(this.handleError);
}
**data in console w/o any **
{{this.res}} in html
I'm pretty sure you don't have to put any at this line in app.service.ts
return this.http.get<any>(this.urlNorth,{responseType:'text', headers: headers})
because get method expects 0 type arguments.
Type any is not the problem. It's just TypeScript annotation to organise your code. The problem is you are refering to the res in inline template as this.res, but you should just res. However it won't work as you think. Looking at your data structure You will have to iterate throught this data due to Table is an array. Additionaly I Highly suggest to always represnt your data as class
export class Apps {
public Table: Array<any>; //here should be another type instead of "any"
/* rest of data if any */
}
Back to your question you should have in your html file <div>{{res}}</div> but that's just print your object as string if I good remember. So to properly access your data you should iterate through table using *ngFor
<div *ngFor="let el of res.NewDataSet.Table">
<span>{{el.BackColor}}</span>
<!-- all other data -->
</div>
It looks as though the data is coming back. I'll answer your initial question first (since you added a few issues in comments):
My guess is when you get data back, it's not showing because it's HTML, and angular doesn't like injecting html.
Add this to your TS:
import { DomSanitizer, SafeHtml } from '#angular/platform-browser';
res[]: safeHTML;
And change your html to this:
<div [innerHTML]="res"></div>
As mentioned in a previous answer, this is a solution for a single return of res, not an array of different htmls. If it's an array, you'll have to handle it accordingly. for instance:
<ng-container *ngFor="let r of res">
<div [innerHTML]="r">
</ng-container>

Load Script Tag in Angular 2 App When Src Attribute is from Web API Call

Context:
I have an Angular 2+ application that makes calls to a web API containing URLs for a src attribute on a script tag that is created by a loadScript function in the AfterViewInit lifecycle hook.
The web API returns a JsonResult and is yielding the data I expect. I was able to interpolate some of the data in the component's template.
Additionally, before I added the call to the web API, the loadScript function was working with a hard-coded argument.
Reading a thread on github. A "member" stated that scripts are not supposed to be loaded on demand. So what I implemented with the loadScript function is essentially a work around, but how else would load them? I don't want to have a seemingly endless amount of script tags sitting in the index.html file.
import { Component, OnInit, AfterViewInit } from '#angular/core';
import { ActivatedRoute } from '#angular/router';
import { Http } from '#angular/http';
#Component({
selector: 'app-agriculture-roadmap',
templateUrl: './agriculture-roadmap.component.html',
styleUrls: ['./agriculture-roadmap.component.css']
})
export class RoadmapComponent implements OnInit, AfterViewInit {
constructor(private _httpService: Http, private _route: ActivatedRoute)
{
}
apiRoadmaps: { roadmapName: string, pdfRoadmapURL: string, jsRoadmapURL: string };
ngOnInit() {
this._httpService
.get('/api/roadmaps/' + this._route.params)
.subscribe(values => {
this.apiRoadmaps = values.json() as { roadmapName: string, pdfRoadmapURL: string, jsRoadmapURL: string };
});
}
async ngAfterViewInit() {
await this.loadScript(this.apiRoadmaps.jsRoadmapURL);
}
private loadScript(scriptUrl: string) {
return new Promise((resolve, reject) => {
const scriptElement = document.createElement('script')
scriptElement.src = scriptUrl
scriptElement.onload = resolve
document.body.appendChild(scriptElement)
})
}
}
If you are using angular cli .
Then place these scripts in
angular-cli.json file under scripts array
scripts:[
.....
]
Please refer this [link] (https://rahulrsingh09.github.io/AngularConcepts/faq)
It has a question on how to refer third party js or scripts in Angular with or without typings.

Angular 2 Form Serialization Into JSON Format

I am having a little bit of trouble creating my Angular 2 form and converting the submitted data into JSON format for the use of submitting it to my API. I am looking for something that works very similarly to this example:
$.fn.serializeObject = function()
http://jsfiddle.net/sxGtM/3/The only problem with this example is that the code is written in JQuery, whereas I'm trying to use strictly angular 2.
Any help would be greatly appreciated, I am still very new to angular.
You can use the getRawValue() function if you're using a FormGroup, to return an object that can then be serialized using JSON.stringify().
import { Component, OnInit } from '#angular/core';
import { FormGroup, FormBuilder } from '#angular/forms';
import { Http } from '#angular/http';
#Component({
selector: 'my-component',
templateUrl: 'my-component.component.html'
})
export class MyComponent implements OnInit {
form: FormGroup;
constructor(private fbuilder: FormBuilder,
private http: Http) { }
ngOnInit(){
this.form = this.fbuilder.group({
name: '',
description: ''
});
}
sendToAPI(){
let formObj = this.form.getRawValue(); // {name: '', description: ''}
let serializedForm = JSON.stringify(formObj);
this.http.post("www.domain.com/api", serializedForm)
.subscribe(
data => console.log("success!", data),
error => console.error("couldn't post because", error)
);
}
}
You can use JSON.stringify(form.value):
submit() {
let resource = JSON.stringify(this.form.value);
console.log('Add Button clicked: ' + resource);
this.service.create(resource)
.subscribe(response => console.log(response));
}
Result in Chrome DevTools:
You are looking for JSON.stringify(object) which will give you the JSON represantation of your javascript object.
You can then POST this using the built-in HTTP service to your server.