So I have my data stored in database and I'm extracting in angular and I'm getting the data the problem is when I'm trying to display the data I'm getting the following error. I just need to display the question in html using ngFor* .I'm completely new to angular any guidance will be very helpful .
this.selfHelpService.getFgSelfHelpByName("BYOD").subscribe(data => {
// console.log(data);
const BYOD = JSON.parse(data["data"]);
// console.log(BYOD );
});
<div class="cards" *ngFor="let BYOD of BYOD">
<div class="read-1">
{{BYOD.posts.question}}
</div>
</div>
since you are getting the data, you can do the following:
// If this is your response:
{"BYOD":[ ` { "posts": [ {"Question":"BYOD (Android)","answer":"???"}, {"Question":"BYOD (IOS)","answer":"?????"} ] } ] };
this.selfHelpService.getFgSelfHelpByName("BYOD").subscribe(data => {
try {
const BYOD = JSON.parse(JSON.stringify(data["data"]));
} catch(err) {
console.log('Try catch error ==>', err);
}
// Declare a variable in the component.ts above constructor called byodPostsData
// Assign the values to that variable
this.byodPostsData = BYOD[0].posts;
});
// In your HTML now, simply loop through the this.byodPostsData;
<div class="cards" *ngFor="let eachPost of byodPostsData">
<div class="read-1" *ngIf="eachPost && eachPost.question">
{{ eachPost.question }}
</div>
</div>
As mentioned earlier by other commentators here: Am not sure why you are using JSON.parse(). But if you should use it for sure, then try using this:
// Generally its considered good practice to use try-catch for JSON.parse() for data
try {
const BYOD = JSON.parse(JSON.stringify(data["data"]));
} catch(err) {
console.log('Try catch error ==>', err);
}
I am not sure what you are trying to loop, but, if you want to loop over byod,
<div class="cards" *ngFor="let byod of byod.BYOD[0].posts">
<div class="read-1">
{{byod.Question}}
</div>
</div>
Besides in your example code, byod is locally scope in the function, you should make a component variable from that to make it accessable by the HTML.
Feel free to ask if something is unclear.
As you are new to Angular: this is how decided to access the response:
The 0 should come from the fact that the response is a JSON object with a JSON key BYOD which has an array as value: so the BYOD[0] indicates that you are trying to access the first item of the array from BYOD, which is another object with the JSON key "posts", the value of "posts" is an array you want to loop over. If you parse the data from the request to a component property called byot, it should be accessable in the html the following: byod.BYOD[0].posts I hope I made it a bit more clear.
Here is a stackblitz!
https://stackblitz.com/edit/angular-ivy-jcxgfo?file=src/app/app.component.ts
Related
Im trying to fetch Data from an API and pass it into my component as props. The Problem is I get this type error. Some googling showed, that the API seems to return an object and the map() function is expecting an Array. Okay, console logged what I get from the API and it is indeed an object. Easy fix right? However, none of the fixes I found for this work. This is my original code with the error:
export async function getStaticProps(context) {
const res = await fetch("https://rezepte-api-test.babafresh.de/recipes.json")
const data = await res.json()
return {
props: { recipes: data }, // will be passed to the page component as props
}
export default function Test(recipes) {
console.log(typeof recipes);
return (
<div>
<ul>
{recipes.map((recipe) =>(
<div key={recipe.name}>
<li>{recipe.name}</li>
</div>
))}
</ul>
</div>
);
I Did try some of the following fixes I found here, but none of my recipes from the array get rendered. Im in front of a white page, is my map function wrong here?
export default function Test(recipes) {
let arr = Object.entries(recipes);
return (
<div>
<ul>
{arr.map((recipe) =>(
<div key={recipe.name}>
<li>{recipe.name}</li>
</div>
))}
</ul>
</div>
);
Id appreciate any pointers.
From your first snippet, not sure this return statement at the top-level execution context is correct or what you intended to do.
return {
props: { recipes: data }, // will be passed to the page component as props
}
And call to the receipes api returns an array not an object
So what you are doing with Object.entries is incorrect. Simple, use the arrayed props with the map function in JSX.
For the shortest fix,
let arr = receipes.receipes;
P.S. If you think this set of API data is only meant for this component and will not be shared, try using the useEffect hook to fetch the data inside this component itself and render.
export default function Test() {
const [receipes, setReceipes] = useState('');
useEffect(() => setReceipes(await fetch("https://rezepte-api-test.babafresh.de/recipes.json").then(res => res.json())), []);
return (
<div>
<ul>
{receipes.map((recipe) =>(
<div key={recipe.name}>
<li>{recipe.name}</li>
</div>
))}
</ul>
</div>
);
}
The API is returning an array of objects only.
To access the data from the API, you can just map over it as it an array
<div>
<ul>
{res.data.map((recipe) =>(
<div key={recipe.name}>
<li>{recipe.name}</li>
</div>
))}
</ul>
</div>
Are you using useEffect? Usually these problems are related to async fetching and initially getting undefined or empty lists etc. as a prop before data is actually available. If you are using effect, then try to catch the first error by calling map only if recipes is defined.
For your second solution: check the contents of arr by logging it.
I'm using Angular 4 to develop an app which is mainly about displaying data from DB and CRUD.
Long story short I found that in Angular 4 the component html doesn't like displaying loosely typed object (leaving the space blank while displaying other things like normal with no warning or error given in console) even if it can be easily displayed in console.log output, as shown in a string.
So I made a function in the service file to cast the values into a set structure indicating they're strings.
So now something like this works:
HTML
...
<div>{{something.value}}</div>
...
Component.ts
...
ngOnInit() {
this.route.params.subscribe(params => {
this.pkey = params['pkey'];
this.service.getSomethingById(this.pkey)
.then(
something => {
this.something = this.service.convertToStructure(something);
},
error => this.errorMessage = <any>error);
});
}
...
Code of the function convertToStructure(something)
convertToStructure(someArr: myStructure): myStructure {
let something: myStructure = new myStructure();
something.value = someArr[0].value;
return something;
}
But as I dig into other files for copy and paste and learn skills from what my partner worked (we're both new to Angular) I found that he did NOT cast the said values into a fixed structure.
He thought my problem on not being able to display the values (before I solved the problem) was because of me not realizing it was not a plain JSON object {...} but an array with a single element containing the object [{...}] .
He only solved half of my problem, cause adding [0] in html/component.ts was not able to make it work.
Component.ts when it did NOT work
...
ngOnInit() {
this.route.params.subscribe(params => {
this.pkey = params['pkey'];
this.service.getSomethingById(this.pkey)
.then(
something => {
console.log(something[0].value); //"the value"
this.something = something[0]; //html can't find its value
},
error => this.errorMessage = <any>error);
});
}
...
HTML when it did NOT work
...
<div>{{something[0].value}}</div> <!--Gives error on the debug console saying can't find 'value' of undefined-->
...
And of course when I'm using the failed HTML I only used this.something = something instead of putting in the [0], and vice versa.
So I looked into his code in some other page that display similar data, and I found that he used *ngFor in html to extract the data and what surprised me is that his html WORKED even if both of our original data from the promise is identical (using the same service to get the same object from sever).
Here's what he did in html:
...
<div *ngFor="let obj of objArr" ... >
{{obj.value}}
</div>
...
His html worked.
I'm not sure what happened, both of us are using a raw response from the same service promise but using for loop in html makes it automatically treat the value as strings while me trying to simply inject the value fails even if console.log shows a double quoted string.
What's the difference between having the for loop and not having any for loop but injecting the variable into html directly?
Why didn't he have to tell Angular to use the set structure indicating the values are strings while me having to do all the trouble to let html knows it's but a string?
The difference here is as you said that your JSON is not simple object , its JSON Array and to display data from JSON array you need loop. So, that is why your friends code worked and yours did not. And please also add JSON as well.
I am currently getting json object from server and the object also has many nested json object as well. So far, I've been using *ngFor = "let a of data | pipe" (the pipe to get deeply nested value) and single interpolation {{a.value['someValue']}} to get the deep nested value of json object for other situations but this isn't serving my purpose right now since I don't want to loop my json.
Is there any way to get deeply nested json value without using ngFor?
The part of json object I am getting from server.
UserProfile:
{name: 'Jess'
University: 'UC Berkley'
Major: 'Media Communication'
birthday: 1994}
categoryInfo:
["inish work with quality"]
currentArea
:"CA"
introInfo {
experience: [
0: {Company: 'Atlas', workingYears: 1, **recLetter**:'She was on time always,
never late. The quality of her work is very high-level.'}
1: {Company: 'Footstep', workingYears: 2, recLetter:'She was on time always,
never late. The quality of her work is very high-level.'}
]
introduction: "Hello I'm Jess"
}
And if I use aforementioned method, it will just loop 4 keys (UserProfile, categoryInfo, currentArea, and introInfo) which I don't want.
How can I get value that's in bold (recLetter) without using *ngFor?
in my component, I am doing this.
userInfo: UserDetailInfo[];
getUserDetail(): void {
this.userDetail.getUserDetail()
.subscribe
(
userInfo => this.userInfo = userInfo,
error => this.errorMessage = error
)
}
And I tried this in the html template but didn't work and I didn't know how to get 'recLetter'
{{userInfo.experience['0']}}
Please help!
Thank you in advance
For the starters, lets assume you get experience array always the same, with 2 elements.
The only thing that you need to do in the html is this:
{{ userInfo.experience[0].recLetter }}
In case you want to loop through the whole array exeperience and display recLetter you can do this:
<div *ngFor="let item of userInfo.experience">
{{item.recLetter}}
</div>
Try this
properties.pipe.ts
import {Pipe} from '#angular/core';
#Pipe({name: 'properties'})
export class PropertiesPipe {
transform(o: {}) {
return Object.entries(o).map(([key, value]) => ({
key,
value
}));
}
}
app.module.ts
import {propertiesPipe} from './properties.pipe';
#NgModule({
declarations: [PropertiesPipe, /* whatever else was here */],
// ... whatever else was here
}) export class AppModule { }
component.html
<ul>
<li *ngFor="property of userInfo | properties">
<span *ngIf="!Array.isArray(property.value)">
{{property.key}}: {{property.value}}
</span>
<span *ngIf="Array.isArray(property.value)">
{{property.key}}: <span *ngFor="value of property.value">{{value}}, </span>
</span>
</li>
</ul>
This is a follow up question to one I posted here: (I have 2 records in a database Vue outputs 8 records). In that question, was having trouble fetching a JSON list of games for an online casino I'm building. In my original question, Vue was unable to load the JSON as JSON, but now that's fixed.
I am now trying to parse this JSON using Vue to loop through all of the games in the games array and print either In progress or Game is joinable. However, instead of getting 8 different records from the database (from a weird response array object returned by this.$http.get. I now see that my JSON list is seemly being ignored by my Vue template; none of the objects in the collection get outputted (again either In progress or Joinable. I just get a blank list.
Is my v-if conditional programmed correctly? I checked the documentation and everything seems to be set up correctly. I find it odd that neither the v-if, or v-else, divs> are executed.
vuewgames.blade.php
#extends('app')
#section('content')
<strong>Below is a list of joinable games</strong>
<div class="container">
<games></games>
</div>
<div id="games-list">
<template id="games-template">
<ul class="list-group">
<li class="list-group-item" v-for="game in games">
<strong>play against #{{ game.player1 }}</strong>
</li>
</ul>
<pre>#{{ games | json }}</pre>
</template>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-resource/1.0.3/vue-resource.js"></script>
<script src="js/all.js"></script>
#endsection
all.js
Vue.component('games', {
template: '#games-template',
data: function() {
return {
games: []
};
},
created: function () {
var self = this;
this.$http.get('/api/games').then(function (response) {
// fetch array from jsoN object
response.json().then(function (games) {
console.log(games);
});
});
},
});
new Vue({
el: 'body'
});
The reason that you're not getting the information to the instance is due to scope.
When you're using closures in javascript the scope of the this isn't the containing object.
One way to get around this is to assign this to another variable outside of the function and then use that instead. You should be able to get it working by changing your created method to be:
created: function () {
var self = this;
this.$http.get('/api/games').then(function (response) {
// fetch array from jsoN object
response.json().then(function (games) {
self.games = games;
});
});
},
Hope this helps!
I am trying to pass a simple variable value into an HTML file using ember.js. My value is contained within a json file called value.json.
My HTML code is as follows:
<h1>I won {{App.moneyvalue}} today!</h1>
However when I pass the json call via ember, it think that the entire call is a variable:
App = Ember.Application.create({
moneyvalue: function () {
return $.getJSON( "js/value.json", function( data ) {
return data.tot;
});
}
}
And returns the following:
I won function () { return $.getJSON( "js/donors.json", function( data ) { return data.tot; }); } today!
As it seems to think that moneyvalue is a string variable as opposed to a value?
The jSON file is superbasic
{
"tot": 100
}
Where is this going wrong?
you're supplying Handlebars with a function, generally you would use a computed or normal property on the object. In this case you really just shouldn't define it in the application scope either, I'd recommend using an application route (it's the root route of your app).
App.ApplicationRoute = Ember.Route.extend({
model: function(){
return $.getJSON( "js/value.json");
}
});
Then in your handlebars just use
<h1>I won {{tot}} today!</h1>
Here's an example: http://emberjs.jsbin.com/OxIDiVU/576/edit