I create a json file like
{ "tests": { "CHE": { "Failover": [ "Standalone Box Restart" ],
"Smoke": [ "All Domains Are Published", "No FID Duplication", "PE and
RIC Mangling", "Real Time Updates - FTN", "Only One Response Message
Per Constituent", "LIVE-STANDBY-LIVE Switch" ] }, "Queries": {
"Queries": [ "Get Services For Region" ] } } }
How to show on the HTML like a tree really hurry up. Thank you
Like That:
enter image description here
You can try like this way.
First of all you need to create pipe using ng generate pipe testPipe (this will also import the dependency in app.module.ts file) for converting the object to array for looping through the elements.
test-pipe.pipe.ts
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({
name: 'keys'
})
export class TestPipePipe implements PipeTransform {
transform(value, args:string[]) : any {
let keys = [];
for (let key in value) {
keys.push({key: key, value: value[key]});
}
return keys;
}
}
In your template file place below mentioned code.
<div *ngFor="let item of data | keys">
<ul>
<li>
{{item.key}}
<ul *ngFor="let inItem of item.value | keys">
<li>
<input type="checkbox" name="">{{inItem.key}}
<ul *ngFor="let ininItem of inItem.value | keys">
<li>
<input type="checkbox" name="">{{ininItem.key}}
<ul *ngFor="let inininItem of ininItem.value | keys">
<li>
<input type="checkbox" name="">{{inininItem.value}}
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
in your component file you can right like.
data = { "tests": { "CHE": { "Failover": [ "Standalone Box Restart" ], "Smoke": [ "All Domains Are Published", "No FID Duplication", "PE and RIC Mangling", "Real Time Updates - FTN", "Only One Response Message Per Constituent", "LIVE-STANDBY-LIVE Switch" ] }, "Queries": { "Queries": [ "Get Services For Region" ] } } }
Related
how can I print the key and value of the object inside the template?
The template is 'kendo chart series item tooltip'
My HTML
<kendo-chart-series-item-tooltip>
<ng-template let-value="value" let-category="category" let-series="series" let-dataItem="dataItem">
<div *ngFor="let item of dataItem.subObject| keyvalue">
{{item | json}}<br/>
Key:{{item.key}} and Value:{{item.value}}
<br/><br/>
</div>
</ng-template>
</kendo-chart-series-item-tooltip>
My JSON:
[
{
"id": "1Period",
"subObject": [{"Alex":"10"},{"Mathew":"5"}],
},
{
"id": "2Period",
"subObject": [{"Alex":"2"},{"Mathew":"50"}]
}
]
This code doesn't work and it returns this error:
Uncaught Error: Template parse errors:
The pipe 'keyvalue' could not be found
probably you want to set it like this
{
"id": "1Period",
"subObject": [
{
"key":"Alex",
"value":"10"}
}
and your HTML file like this
<kendo-chart-series-item-tooltip>
<ng-template >
<div *ngFor="let item of dataItem.subObject">
<br/>
Key:{{item.key}} and Value:{{item.value}}
<br/><br/>
</div>
</ng-template>
</kendo-chart-series-item-tooltip>
You can define the following custom pipe:
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({
name: 'forObject'
})
export class ForObjectPipe implements PipeTransform {
transform(value: object): string[] {
if (!value) {
return [];
}
return Object.keys(value);
}
}
And use it like that:
<kendo-chart-series-item-tooltip>
<ng-template let-value="value" let-category="category" let-series="series" let-dataItem="dataItem">
<div *ngFor="let key of dataItem.subObject | forObject">
{{dataItem.subObject[key] | json}}<br/>
Key:{{key}} and Value:{{dataItem.subObject[key]}}
<br/><br/>
</div>
</ng-template>
</kendo-chart-series-item-tooltip>
Check out my boilerplate if you have issues defining the pipe.
I had request data from API, then I got response Object, so using *ngFor, I had managed to display some data that I want, problem is that are some css need to be implemented based on response attribute, for my data, I had list of bank and status. based on attribute status Offline
I need to change background color and need only show Offline status only.I had managed to change the background color, this is what I had tried:
html file
<ul class="ul1">
<li
[style.background]="getBackgroundColor(p.status)"
class="li1" *ngFor="let p of myData?.paymentChannels">
<span>{{p.name}}</span>
<br>
<span>{{p.status}}</span>
</li>
</ul>
ts file
getBackgroundColor(status) {
switch (status) {
case 'Offline':
return 'grey';
}
}
expected output:
also this is my stackblitz demo, I could use some suggestion to solve mine.
I would suggest something like this:
<ul class="ul1">
<li
[ngClass]="{offline: p.status == 'Offline'}"
class="li1" *ngFor="let p of myData?.paymentChannels">
<span>{{p.name}}</span>
<br>
<span> {{p.status == 'Offline' ? p.status : ' '}}</span>
</li>
</ul>
And add to css:
.offline {
background-color: gray;
}
your code is working but I think it's better without function like this:
<ul class="ul1">
<li [style.background]="'grey' : p.status == 'Offline'" class="li1"
*ngFor="let p of myData?.paymentChannels">
<span>{{p.name}}</span>
<br>
<span>{{p.status}}</span>
</li>
</ul>
Before
<span>{{p.status}}</span>
After
<span>{{p.status === 'Offline' ? 'Offline' : ' '}}</span>
It would be even better if you would extract the logic to a method withing the TS file.
The ' ' part is a placeholder (blank space) so the box do not collapse, but I would recommend adding the proper CSS styling, for instance, adding min-height: 36px; to the class .li1 would suffice.
StackBlitz
You can filter your data using structural directive *ngIf and then apply styling:
<ul
*ngIf="myData?.paymentChannels"
class="ul1">
<li
[style.background]="p?.status === 'Offline'? 'grey' : 'green'"
class="li1"
*ngFor="let p of myData?.paymentChannels">
<ng-container *ngIf="p?.status === 'Offline'">
<span>{{p.name}}</span>
<br>
<span>{{p.status}}</span>
</ng-container>
</li>
</ul>
If you want to filter and your array of data is small, then you can use *ngIf directive. However, it would be better to use filter pipe:
<li *ngFor="let item of myData?.paymentChannels | yourFilter:filterargs">
and your pipe:
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({
name: 'myfilter',
pure: false
})
export class YourFilterPipe implements PipeTransform {
transform(items: any[], filter: Object): any {
if (!items || !filter) {
return items;
}
// filter items array, items which match and return true will be
// kept, false will be filtered out
return items.filter(item => item.title.indexOf(filter.title) !== -1);
}
}
and you should include your pipe into app.module.ts:
import { YourFilterPipe } from './shared/pipes/your-filter.pipe';
#NgModule({
imports: [
..
],
declarations: [
YourFilterPipe,
],
providers: [
..
],
bootstrap: [AppComponent]
})
export class AppModule { }
Please, see the example at stackblitz.com
UPDATE:
If you do not want to filter data, but hide status offline you can use *ngIf structural directive:
<ul
*ngIf="myData?.paymentChannels"
class="ul1">
<li
[style.background]="p?.status === 'Offline'? 'grey' : 'green'"
class="li1"
*ngFor="let p of myData?.paymentChannels">
<span>{{p.name}}</span>
<br>
<span *ngIf="p?.status === 'Offline'; else empty">{{p.status}}</span>
<ng-template #empty>$nbsp;</ng-template>
</li>
</ul>
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>
I want to display content from the firebase I get the data from HTTP get request and I want to display it using ngFor
here is how i get the data
///a service
getMessages(){
return this.http.get('https://bigproject-dd88e.firebaseio.com/data.json')
.map((response:Response)=>{
const data: Message[]=response.json();
return data;
}
).catch(
(error:Response)=>{
return Observable.throw('something went wrong');
}
);
}
and here is my component
export class MessagesComponent implements OnInit {
Message=[];
constructor(private global:GlobalService) {
}
ngOnInit() {
this.GenaerateMessages();
}
GenaerateMessages(){
this.global.getMessages().subscribe(
Message=>this.Message=Message
);
}
}
and here is my HTML
<div *ngFor="let item of Message | keyvalue">
<p>{{item.value|json}}</p>
</div>
I get this on the screen
[ { "email": "loay-gohan#hotmail.com", "message": "loayy", "name": "loay", "phone": "123123123" } ]
[ { "email": "example#example", "message": "hi", "name": "..", "phone": "123123" } ]
how can I reach the inside fields name, message, phone...
it looks like eachitem.value contains one array with one object. If this is a case you can reach it like this:
<div *ngFor="let item of Message | keyvalue">
<div>EMAIL: {{ item.value[0].email }}</div>
<div>MESSAGE: {{ item.value[0].message }}</div>
<div>NAME: {{ item.value[0].name }}</div>
<div>PHONE: {{ item.value[0].phone }}</div>
<pre>{{ item.value | json }}</pre>
</div>
If item.value array has more than one object you might want to loop it wit additional inner ngFor
You do not use value.key. Don't you need it?
I am new to angular,
I have created a service to loop the nested json data for my list.
export const CATEGORIES: Category[] = [
{
id: 1,
categoryName:'Accessories',
subcatName: [
{subcategory: 'belts',}
],
},
{
id: 2,
categoryName:'Clothing',
subcatName: [
{subcategory: 'jeans}',
],
},
];
and
#Injectable()
export class CategoriesService {
constructor() { }
getCategories(): Category[]{
return CATEGORIES;
}
}
I am trying to loop this data on my list
<ul>
<li *ngFor="let cat of categoryList">
{{cat.categoryName}}
<ul>
<li *ngFor="let subcat of categoryList">
asdad {{subcat.subcategory}}
</li>
</ul>
</li>
</ul>
For this I have added code in component .ts file
export class CategoriesComponent implements OnInit {
categoryList: Category[];
constructor(private categoryservice: CategoriesService) { }
ngOnInit() {
this.categoryList = this.categoryservice.getCategories();
}
}
Please help, I want to create a navbar list of categories, when upon hover it shows the relevant subcategory. Please let me know if you need additional information.
in the inner loop, you should loop over the inner array
<ul>
<li *ngFor="let cat of categoryList">
{{cat.categoryName}}
<ul>
<li *ngFor="let subcat of cat.subcatName">
asdad {{subcat.subcategory}}
</li>
</ul>
</li>
</ul>
Your inner loop should iterate over cat of the parent not categoryList
Change
From
<li *ngFor="let subcat of categoryList">
asdad {{subcat.subcategory}}
</li>
To
<li *ngFor="let subcat of cat.subcatName">
asdad {{subcat.subcategory}}
</li>