sorry for the noob question. I created an http request and retrieved some pokemon data and put it in an object called pokemon, like so:
export class AppComponent implements OnInit{
title = 'Pokedex';
apiURL = 'https://pokeapi.co/api/v2/pokemon/1';
pokemon = {};
constructor(private http: HttpClient){}
ngOnInit(): void{
this.http.get(this.apiURL).subscribe(data =>{
const pokemon = {
name: data['name'],
id: data['id'],
abilities: data['abilities'].map( ability => ability['ability']['name']),
types: data['types'].map( type => type['type']['name']),
image: data['sprites']['front_default']
}
In the HTML, I tried to create an image with <img src = "{{ pokemon.image }}"/>
However, the only thing that appears is a broken image icon and this error apears:
GET http://localhost:4200/%7B%20pokemon.image%20%7D 404 (Not Found)
But when I console.log pokemon.image, the full URL is output to the console:
https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/1.png
What am I doing wrong here?
You can try it with this instead:
<img [src]="pokemon.image"/>
If this still not works, can you tell me what is the reflected value of that property in your HTML file?
<p>{{ pokemon.image }}</p>
I made two changes and its working :
1) pokemon:any; (instead of pokemon = {};)
2) this.pokemon (instead of const pokemon)
Related
service/config file:
import { Injectable } from "#angular/core";
import { SafeHtml } from "#angular/platform-browser";
#Injectable()
export class xxxxxConfig {
xxxVaultLink: SafeHtml;
whatHappensNextItemsForEmailxxx: string[];
whatHappensNextItemsForEmailSubTextxxx: string[];
constructor() {
this.xxxVaultLink = `xxx xx`;
this.whatHappensNextItemsForEmailxxx = [
`Confirmation of payment and a copy of your receipt has been emailed to you. You should receive it shortly.`,
`xxxx will send your xxxxxdocuments (xxxxx) by post within 5 days.`,
`A copy of your renewal xxxxx along with any supporting docs can be found in your
${this.xxxVaultLink} within the next 2 - 3 days.`,
];
this.whatHappensNextItemsForEmailSubTextxxx = [
`(If you wish to receive your receipt by post, please contact us on 08xxxxx)`,
`Important: please ensure that you keep your documents safe as they form the basis of your xxxx with xxx.`,
``,
];
}
I'm trying to add a link to the third item in the array above i.e. ${this.xxxVaultLink} but it shows all of the html including tags i.e. <\a href="https://www.w3schools.com" target="_blank">xxx xx</a>
Accessing it from the component below
Component file:
whatHappensNext() {
if (!this.isxxxxy) {
this.whatHappensNextItems = this.isxxxxPhoneNumber
? this.xxxxConfig.whatHappensNextItemsForEmailxxx
: this.xxxxConfig.whatHappensNextItemsForPost;
this.whatHappensNextItemsSubText = this.isxxxxPhoneNumber
? this.xxxxConfig.whatHappensNextItemsForEmailSubTextxxx
: this.xxxxConfig.whatHappensNextItemsForPostSubText;
}
}
Not sure if this makes sense but it would be great if one of you guys could tell me how to display the html/link in this config/service file
You're missing possibly the most important part, which is the template showing us how you're attempting to show these string values.
I'll take a stab in the dark and assume it's something like this:
<div>{{myText}}</div>
If you want to slap some HTML in there, try this:
<div [innerHTML]="myText"></div>
I am an Angular beginner and I've made a service and made all the set up so that the Get method works on a JSON file and it worked! but the problem is whenever I want to access to the data inside the JSON file it tells me that it is undefined, and I want to use it as an object in the ts file.
It works when using data biding like this {{stats | JSON}}, but I couldn't use it in the TS. can I convert this 'undefined' to a simple object?
stats: any;
constructor(private statsData: StatDataService) {
this.statsData.GetEmbedded().subscribe((data: any) => {
this.stats = data;
});
}
`
for example I can't use stats.preOrders[0]
To better understand the situation, let's create an example.
example.component.ts
interface Statistics {
median: number;
average: number;
}
export class Example {
// stats is undefined until GetEmbedded() fires
stats?: Statistics;
constructor(private statsData: StatDataService) {
this.statsData.GetEmbedded().subscribe((stats: Statistics) => {
this.stats = stats;
});
}
}
example.component.html
<div>The median is: {{ stats.median }}</div>
Why will this example result in an error? Your variable stats initially is undefined, so it will not have any properties. GetEmbedded() will take some milliseconds to fire but in the same time, the template already tries to access stats.median.
One option to solve this problem would be to check if the variable stats is not undefined and if it is not, access the properties you need.
example.component.html
<div *ngIf="stats">The median is: {{ stats.median }}</div>
In MongoDB 'certificate' collection have '_id, studentID, file' fields. Simply I can input for each document where data type for '_id' and 'studentID' are the string, and file data type is Binary (this binary auto-generated by MongoDB during insertion for each user pdf file).
From fetched data, I can display into angular (e.g StudentID, SchoolName) but only I can't display pdf from fetched binary data into angular
In node server: (app.js) // given the core code to avoid too long reading
// This for inserting data into MongoDB
**var fs = require('fs');
var pdfBinary = fs.readFileSync("./TestingPurpose.pdf");
var pdf = new mongodb.Binary(pdfBinary);**
db.collection('Test').insert({
dateTime: new Date(dateTime),
studentName: studentName,
Principal: principalName,
file: pdf }
After successfully data importing in MongoDB can see data in MongoDB as below:
{
"_id" : "C1135",
"dateTime" : ISODate("2019-01-23T11:45:52.254+01:00"),
"studentID" : "stu123",
"schoolName" : "XXX Primary School",
"file" : BinData(0,"JVBERi0xLjcNCiW1tbW1DQoxIDAgb2Jq... more 101410 bytes - application/pdf")
}
certificate.model.ts: file
export class Certificate {
_id: string;
dateTime: string;
studentID: string;
schoolName: string;
file: any;
}
Then in Frontend Angular use (user.service.ts) to receive all infro from Node (app.js)::
import { Certificate } from '../model/certificate.model';
cert: Certificate[];
// receiving all students info
getCertificates() {
return this.http.get('http://localhost:5600/aziz/displayAllCertificates');
}
// to get always get an instant update I use refreshGetCertificates()
refreshGetCertificates() {
this.chkSubscrip = this.getCertificates().subscribe((res) => {
this.cert= res as Certificate[];
});
}
In Certificate Component:
(certificate.component.ts):
export class CertificatesComponent implements OnInit, OnDestroy {
myPDF: any;
constructor(
public userService: UserService,
private dialog: MatDialog,
) { }
ngOnInit() {
this.userService.refreshGetCertificates();
}
pdfView(receiveObj) {
this.forPDF = !this.forPDF;
const myUint8 = new Uint8Array(receiveObj);
this.myPDF= myUint8;
}
}
(certificate.component.html):
<div class="rows">
<ul class="settings_test headerclass text-center">
<li style="float: left">ID</li>
<li>Student-ID</li>
<li>School</li>
<li>PDF View</li>
</ul>
</div>
<div *ngFor="let eachCerts of userService.cert">
<div class="row">
<div class="settings_test">
<li style="width:10%">{{eachCerts._id}}</li>
<li style="width:10%">{{eachCerts.studentID}}</li>
<li style="width:10%">{{eachCerts.schoolName}}</li>
<li style="width:10%"> <button (click) ="pdfView(eachCerts.file)"> View as PDF </button></li>
<object *ngIf=forPDF data="{{myPDF}}" ></object>
</div>
</div>
</div>
In each row will show ID, StudentID, SChool-Name and a button('View as PDF'), when the button will be clicked then a popup or a new window will appear to display the pdf file from the fetched pdf binary data.
As posted in the comments, you can use this answer that should solve your issue, with this modification:
At the beginning, you have to convert your data into a blob. In your case that would be:
public getPDFFromFile(file /* place here the correct type of your class*/): Blob {
return new Blob([file.buffer])
}
then you should be able to use the above mentioned answer. As note by MongoDB documentation, you can access the internal binary data via the buffer property which is of type Buffer.
In my application their is some text which is coming from a constant file which is declared like this:
export const EmpStrings = {
data: "Welcome {{employee.name}}"
}
And In my component file there is an object called employee.
public employee = { name: 'xyz', dept: 'EE' }
Now In my HTML I want to use it like this:
<div class='e-data' [innerHTML] = "EmpStrings.data"></div>
But this didn't seems to be working.
I tried various variations:
[inner-html] = "EmpStrings.data"
[innerHTML] = {{EmpStrings.data}}
[innerHTML] = "{{EmpStrings.data}}"
But none of them seems to be working.
If you don't want to use JitCompiler then you can parse string yourself
component.ts
ngOnInit() {
this.html = EmpStrings.data.replace(/{{([^}}]+)?}}/g, ($1, $2) =>
$2.split('.').reduce((p, c) => p ? p[c] : '', this));
}
template
<div [innerHTML]="html"></div>
Plunker Example
use ${employee.name} to bind angular variable to innerHTML
"data": `Welcome ${employee.name}`
Angular doesn't interpolate strings like this, as far as I know one of the reason is security. The const doesn't have the context where your employee is in hence you see the error saying employee is not defined.
You could do this:
Change your constant:
export const EmpStrings = {data: "Welcome "};
then:
<div class='e-data'>{{EmpStrings.data}}{{employee.name}}</div>
But if for some reason you must use [innerHTML]:
In your component class, add a method:
getWelcomeMessage(){return EmpStrings.data + this.employee.name;}
in the component view:
<div class='e-data' [innerHTML] = "getWelcomeMessage()"></div>
I'm working on an Angular 2 application, and I'm trying to use JSON data, either local/mocked or fetched via HTTP, and display it on a component. I have an injectable service that will do the fetching/mocking -
import { Injectable } from 'angular2/core';
#Injectable()
export class TestService {
testString:string = "";
testDetails: string = "";
constructor() { }
getTestDetails(): Promise<string> {
this.testDetails = {
"status": "success",
"message": "Data save successful",
"data": {
"Random_Data_1": "Random Data 1",
"Random_Data_2": "Random Data 2"
}
};
return Promise.resolve(JSON.stringify(this.propertyDetails));
}
}
And then I have a component that uses the service via Dependency Injection -
import { Component, OnInit } from 'angular2/core';
import {TestService} from "./test.service";
#Component({
selector: 'test',
templateUrl: './test.component.html',
styleUrls: []
})
export class TestComponent implements OnInit {
testDetails: string = "";
constructor(private testService: TestService) { }
ngOnInit() {
this.display();
}
display(): void {
this.testService.getTestDetails()
.then(
testDetails => {
this.testDetails = JSON.parse(testDetails);
},
errorMessage => {
console.error("Something failed trying to get test details");
console.error(errorMessage);
}
);
}
}
The component HTML -
<div class="content">
<p> Test Details </p>
<p> {{ testDetails.data.Random_Data_1 }} </p>
</div>
The problem is, the HTML is erroring out trying to display the items in the testDetails JSON. I initially used it with md-tabs, so the first try would error out, but the other tabs would read the data fine. Also, the ngOnInit would be called twice when the error occurs. I have narrowed it down to the data coming in and the object types that is causing me the headache.
I know I can create a Details class and declare testDetails of type Details, and then map the JSON data into the class, but the thing is, I want to work with generic data, and only know a few components that will be present in the data. Is there a way to read the JSON, and use the data without having to define a separate class for each scenario ?
I have a plunker with the most basic stuff set up. The actual setup runs fine on my local system up until where I try to access the JSON data in the HTML, at which point the browser throws a cryptic error. The skeleton code doesn't even run on Plunker. That said, the structure in the Plunker defines the structure of my app and the data flow. Plunker with the basic setup
What is the best way to achieve this ? What is the standard/best practice to do this ?
Throwing another option out there, since you asked about best way to achieve this. Might not be the best idea, this is subjective ;) But if I were you...
Thinking about the future, where you will use real backend, it could be nice to use mock json file. If/when you move over to a real backend, you wouldn't basically need to change anything else but the url of the requests :)
So I set up a simple example for you. Here I used Observables, but you can use Promises if you prefer that. Here's more info on HTTP if you want/need to read up on that. Most important thing is that you have the HttpModule imported in your app module.
You have your file with JSON and in your service make http-requests to that:
getTestDetails() {
return this.http.get('src/data.json')
.map(res => res.json())
}
Your display-method:
display() {
this.testService.getTestDetails()
.subscribe(data => {
this.testDetails = data;
});
}
And in the template use the safe navigation operator to safeguard null/undefined values:
<div class="content">
<p> Test Details </p>
<p> {{ testDetails?.data?.Random_Data_1 }} </p>
</div>
Here's a
Demo
As said, this is to give another approach on how to implement the things you want to achieve, and this would probably be my preferred way :)
Use
<p *ngIF="testDetails.data.Random_Data_1 "> {{ testDetails.data.Random_Data_1 }} </p>
This is because there is no data initially.Hope this helps you.