How present JSON List in Angular HTML with *ngFor - html

I get a result in the JSON Format like these sample from a webservice.
How can i iterate over this items to prensent the objects
HTML Code - not working
<div *ngFor="let item of List">
{{item.Code}}
</div>
JSON Sample
"List": {
"0": {
"Code": "A"
},
"1": {
"Code": "B"
},
"2": {
"Code": "C",
}
}
unfortunally the webservice does not provide this as an Array [] of objects
I want to see the list of all items für the Key "Code"

You can use KeyValuePipe like here.
So the your code would be something like this:
<div *ngFor="let item of List | keyvalue">
{{item.value.Code}}
</div>

As it was not working with
<div *ngFor="let item of List | keyvalue">
{{item.value.Code}}
</div>
Typescript was throwing an error because {{item.value.Code}} was not known.
I did some additional research and found the following solution
<div *ngFor='let key of objectKeys(List)'>
{{List[key].Code}}
</div>
in the typescript class corresponding to the html file you have to add
objectKeys = Object.keys;

Related

How i can do a *ngFor in a array of objects that i don't know the name property?

I have this array called dadosRelatorio that i need to iterate in my template, this array i get in a http request:
[{"id": 1,
"name": "a",
"class":[{
"Inglês":[{
"id": 1,
"code": "teste"
},
{
"id": 2,
"code": "teste 2"
}],
"Espanhol":[{
"id": 1,
"code": "a"
}]
}]
}]
How i can iterate the objects inside class if they have different names property? Sometimes the name can be "Inglês" and sometimes can be "Espanhol" and other names...
When i know the name of the property i do this way:
<div *ngFor="let aluno of dadosRelatorio" class="div-aluno">
<span>Aluno: {{ aluno.name }}</span>
<div *ngFor="let classe of aluno.class">
<div *ngFor="let idioma of classe. ???>
</div>
</div>
</div>
But how i can iterate the object inside class?
You may iterate using the keyvalue pipe as shown below:
<div *ngFor="let aluno of dadosRelatorio" class="div-aluno">
<span>Aluno: {{ aluno.name }}</span>
<div *ngFor="let classe of aluno.class | keyvalue">
<div> {{classe.key}}</div>
<div *ngFor="let type of classe.value | keyvalue">
{{type.key}}
<div *ngFor="let data of type.value | keyvalue">
{{data.value.id }}
{{data.value.code }}
</div>
</div>
</div>
</div>
You can enumerate an object keys using Object.keys.
See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys.
edit: You can also use the keyvalue pipe as describe in the official documentation: https://angular.io/api/common/KeyValuePipe
I thought there was a ngForIn directive as well, but I cant find the doc.

Angular 8 Nested Object Interpolation

This is my version of Angular CLI:
Angular CLI: 7.3.9
Node: 12.2.0
OS: win32 x64
Angular: 8.0.2
While making an Angular 8 application, I am trying to use nested FormGroups which correspond to the following object:
const Boilerplate: any = {
1: {
desc: "section1",
content: {
1: "question 1.a:",
2: "question 1.b:",
3: "question 1.c"
}
},
2: {
desc: "section2",
content: {
4: "question 2.a:",
5: "question 2.b:",
6: "question 2.c",
7: "question 2.d"
}
}
}
There is an inner FormGroup of FormControls for section 1 and section 2, and an outer FormGroup holding the two inner formgroups. This is defined in the component.ts.
In the component.html, I am trying to iterate through the outer FormGroup's inner FormGroups, and print the inner FormControls. This is the code I have so far:
<form [formGroup]="sectionGroup">
<div *ngIf="boilerplate">
<div *ngFor="let section of boilerplate | keyvalue">
{{ boilerplate[section.key].desc }}
<div formGroupName="{{section.key}}">
<div *ngFor="let question of boilerplate[{{section.key}}]">
<-- things -->
</div>
</div>
</div>
</div>
The line <div *ngFor="let question of boilerplate[{{section.key}}]"> fails with an error message of:
Unexpected token {, expected identifier, keyword, or string
I have tried the following solutions, none of which have worked for me:
<div *ngFor="let question of {{boilerplate}}.{{section.key}}">
<div *ngFor="let question of {{boilerplate[section.key]}}">
<div *ngFor="let question of {{boilerplate[{{section.key}}]}}">
<td *ngFor="let question of Section">{{boilerplate[[section.key]]}}</td>
I have tried a variety of other {} and [] combinations and orders, and I realize now that nested interpolation is non-parsable.
Does anyone have a suggestion of how I can achieve this? I am using nested FormGroups because it is possible I will have additional layers of sections in the future. The format of the Boilerplate object can be changed if it would make the problem solvable (because I defined it, myself).
EDIT
The following was the solution that resolved this issue:
<div *ngFor="let question of boilerplate[section.key].content | keyvalue">
{{question.value}}
</div>
I try like below,
<div [formGroup]="formGroup">
<div *ngIf="boilerplate">
<div *ngFor="let section of boilerplate | keyvalue">
{{ boilerplate[section.key].desc }}
<div>
<div *ngFor="let question of boilerplate[section.key].content | keyvalue">
{{ question | json }}
</div>
</div>
</div>
Output is like below,
section1
{ "key": "1", "value": "question 1.a:" }
{ "key": "2", "value": "question 1.b:" }
{ "key": "3", "value": "question 1.c" }
section2
{ "key": "4", "value": "question 2.a:" }
{ "key": "5", "value": "question 2.b:" }
{ "key": "6", "value": "question 2.c" }
{ "key": "7", "value": "question 2.d" }
You need to use a keyValue filter pipe then you could just have the following syntax, this will let you use ngFor* to iterate though objects rather than arrays.
<div *ngFor="let question of boilerplate | keyValue">
{{ question.key }} - {{ question.value }}
</div>
You can then do the same for the nested objects inside until you have the correct data displayed. This is not supported in all versions of Angular, but definitely fine in 8.
Where you have Objects with the key as a number, I would look to manipulate that into an array which would help you keep this a little more simple. Allowing you to use traditional *ngFor
The answer from schoolcoder is great, I just would like to post another example for people in the future with the same problem.
I have an object Block that holds a list of Transactions and I want to show it on my page using two *ngFor's
Block model class:
export class Block {
hash: string;
previousBlockHash: string;
transactions: Transaction[]; <<<<<<<<<<<
merkleRoot: string;
tries: number;
timestamp: number;
}
Transaction model class
export class Transaction {
hash: string;
text: string;
senderHash: string;
signature: string;
timestamp: number;
}
How I show it on my page:
Blocks:
<div class="container">
<ul class="list-group">
<li class="list-group-item" *ngFor="let block of blocks | keyvalue">
Hash: {{blocks[block.key].hash}}<br>
Previous block hash: {{blocks[block.key].previousBlockHash}}<br>
Merkle root: {{blocks[block.key].merkleRoot}}<br>
Tries: {{blocks[block.key].tries}}<br>
Timestamp: {{blocks[block.key].timestamp}}<br>
Transactions in this block:
<ul class="list-group">
<li class="list-group-item" *ngFor="let transaction of blocks[block.key].transactions">
{{[block.key]}}<br>
Hash: {{transaction.hash}}<br>
Text: {{transaction.text}}<br>
SenderHash: {{transaction.senderHash}}<br>
Signature: {{transaction.signature}}<br>
Timestamp: {{transaction.timestamp}}
</li>
</ul>
</li>
</ul>
</div>

How to use nested json object with ngFor

I have a problem iterating through a json object to display messages.
The scenario is that I have messages sent from_id to to_id and the jsonData as follow:
jsonData={
"chat":
{
"79":
{
"from":"Testing Page - joe",
"from_id":79,
"to":"userTestName",
"to_id":1548,
"unread":2,
"messages":
[
{"id":154,"page_id":79,"user_id":1548,"text":"this is the first message to be sent by joe","seen":0,"isgroup":0,"group_id":null,"created_at":"2019-04-10 13:54:10","updated_at":"2019-04-10 13:54:10"},
{"id":155,"page_id":79,"user_id":1548,"text":"this is the second message sent to joe","seen":0,"isgroup":0,"group_id":null,"created_at":"2019-04-11 12:37:39","updated_at":"2019-04-11 12:37:39"}
]
},
"44":
{
"from":"Rock Music Band",
"from_id":44,
"to":"userTestName",
"to_id":1548,
"unread":1,
"messages":
[
{"id":156,"page_id":44,"user_id":1548,"text":"Hello this message from rock","seen":0,"isgroup":0,"group_id":null,"created_at":"2019-04-11 13:18:44","updated_at":"2019-04-11 13:18:44"}
]
}
},
"unread":3
}
I am facing a problem to display these messages in a <ul> using angular *ngFor:
<ul>
<li *ngFor="let messageData of jsonData.chat;>
<div class="message-info">
<h4>{{messageData.from}}</h4>
<h4>{{messageData.messages[0].text}}</h4>
</div>
</li>
</ul>
I'm getting the error of not supported object.
ERROR Error: Cannot find a differ supporting object '[object Object]'
of type 'object'. NgFor only supports binding to Iterables such as
Arrays.
What should my jsonData look like in order to display messages? I want each id 79 - `44' to be a separate object.
jsonData is an object and not an array, therefore the error. You might want to use the KeyValuePipe:
<ul>
<li *ngFor="let data of jsonData.chat | keyvalue>
<div class="message-info">
<h4>{{jsonData.chat[data.key].from}}</h4> <!-- Or even better: data.value.from -->
<h4>{{jsonData.chat[data.key].messages[0].text}}</h4> <!-- Or even better: data.value.messages[0].text -->
<!-- Want to loop through your messages? -->
<ul>
<li *ngFor="let message of data.value.messages">{{message.text}}</li>
</ul>
</div>
</li>
</ul>
Though it might be worth it to transform your data into an array.
You have to format your json as an Array in order for ngFor to work,
I think this is what you are looking for :
https://stackblitz.com/edit/angular-h7ezpn?file=src%2Fapp%2Fapp.component.ts
"chat":
[
{"title" :"79",
"content":
{
"from":"Testing Page - joe",
"from_id":79,
"to":"userTestName",
"to_id":1548,
"unread":2,
"messages":
[
{"id":154,"page_id":79,"user_id":1548,"text":"this is the first message to be sent by joe","seen":0,"isgroup":0,"group_id":null,"created_at":"2019-04-10 13:54:10","updated_at":"2019-04-10 13:54:10"},
{"id":155,"page_id":79,"user_id":1548,"text":"this is the second message sent to joe","seen":0,"isgroup":0,"group_id":null,"created_at":"2019-04-11 12:37:39","updated_at":"2019-04-11 12:37:39"}
]
}},
{
"title" :"44",
"content":
{
"from":"Rock Music Band",
"from_id":44,
"to":"userTestName",
"to_id":1548,
"unread":1,
"messages":
[
{"id":156,"page_id":44,"user_id":1548,"text":"Hello this message from rock","seen":0,"isgroup":0,"group_id":null,"created_at":"2019-04-11 13:18:44","updated_at":"2019-04-11 13:18:44"}
]
}}
],
"unread":3
}

angular 2 ngFor Cannot read property of undefined

I have a nested object with data that I am trying to access with ngFor.
I am able to reach the first part of the data with the first ngFor (app_name, time_stamp etc)
But for some reason I am not getting to the nested object of test_cases. When I try it breaks the whole page and the console keeps telling me "Cannot read property 'test_cases' of undefined" and I can't seem to figure out why...
(first part of) data inside the component:
export class AppComponent {
tests = TESTS;
var TESTS: Test[] = [
{
"app_name": "website",
"time_stamp": "2018-01-20T12:00:00Z",
"test_cases": [
{
"test_name": "View article",
"status": true,
}]
}]
HTML partial:
<div id="tested-app" *ngFor = "let item of tests">
<h2>----<span> {{ item.app_name }} </span>----</h2>
<p id="time"> Time: <span> {{item.time_stamp}} </span> </p>
</div>
<div class="module" *ngFor="let subItem of item.test_cases">
<h3>{{subItem.test_name}}</h3>
</div>
For peeps who are struggling with this:
John Montgomery and Andres M answered this in the comments, I had to put the second div inside the first.

Get nested values from JSON with angularJS

I need to get nested products from JSON to my html in <div ng-repeat="order in orders"></div> I tried many versions of getting products values(name, description etc.) but none of them works. How to do this ?
JSON:
[
{
"id":3,
"date":"00:00:00",
"user":{
"id":1,
},
"orderState":{
"id":1,
},
"products":[
{
"id":1,
"name":"Bosch POF 1200",
"description":"1200W",
"enabled":true,
"price":459,
},
{
"id":9,
"name":"Graphite 58G782",
"description":"a",
"enabled":true,
"price":429,
}
]
}
]
Controller
OrdersService.retrieveAllByCurrentUser().then(function(response) {
$scope.orders = response.data;
console.log(response.data);
}, function(error) {
registerError(error, 'retrieving all orders');
});
The ng-repeat directive creates a new scope, which means that you should be able to loop through the products within it like this:
<div ng-repeat="order in orders">
<div ng-repeat="product in order.products"> e.g. {{product.name}} </div>
</div>
I would also advise to write a directive for dealing with that kind of stuff, because your code can get unreadable really fast. Don't take my word for it though as I am no Angular expert.
Create a nested ng-repeat like this to access the products information:
<div ng-repeat="order in orders">
<div ng-repeat="product in order.products">
<h1 ng-bind="product.name"></h1>
<p ng-bind="product.description"></p>
</div>
</div>
For each order it will go into order.products and loop out the information as product, then you can access the information in product via dot notation, like product.name for example.
You can do nested ng-repeat in html
<div ng-repeat="order in orders">
<div ng-repeat "product in order.products">
<span>{product.name}}</span>
<span>{{product.description}}</span>
</div>
</div>