Nested JSON data loop for *ngFor in angular 5/4 - json

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>

Related

Iterate nested objects using ngFor

I have JSON object:
content =
[
{
"id":1,
"name":"test",
"parent":{
"name":"test2",
"subParent":{
"name":"test3",
"subParent":{
"name":"test4",
"subParent":{
"name":"test5",
"subParent":null
}
}
}
}
}
]
How to iterate through each nested object and display the data in Angular?
I tried to do it with ngFor but it doesn't work
<ul>
<li *ngFor="let data of content">
{{data.id}}
<ul>
<li *ngFor="let p of data.parent">
{{p.name}}
</li>
</ul>
</li>
</ul>
You can try something like that, but recursive templates is for me, the right way to do that.
Regards,

Display content of a list in Angular 2?

I am new in Angular. I am creating a component in which I am creating a list of int. An example of the content of the list is 13,14,15,22,23,24.
I want to display this content on screen in a specific way. I want the continiously integeres to be in one line and the others in the second line. For example I want this:
13:00, 14:00, 15:00 button
22:00, 23:00, 24:00 button
I am trying this but I don't want a continious list, I want two parts of the list.
<ul>
<li *ngFor="let int of listindexdisabled">{{int}}:00 </li>
</ul>
Can someone help?
Why don't we try to set up two loops with a SlicePipe to iterate on a portion ( 13 -> 15 and second loop 2 -> 24 )?
If you have non dynamic list and you list will always need to be cut at a certain index , this should help you
https://angular.io/api/common/SlicePipe
<ul>
<li *ngFor="let int of listindexdisabled | slice:0:3">
{{int}}:00
</li>
</ul>
<ul>
<li *ngFor="let int of listindexdisabled | slice:3:6">
{{int}}:00
</li>
</ul>
otherwise , i think that this should works
<ul>
<ng-container *ngFor="let int of listindexdisabled">
<li *ngIf="int < 22">
{{int}}:00
</li>
</ng-container>
</ul>
<ul>
<ng-container *ngFor="let int of listindexdisabled">
<li *ngIf="int > 21">
{{int}}:00
</li>
</ng-container>
</ul>
You can try this below code
<ul>
<li *ngFor="let int in listindexdisabled">{{int}} : 00</li>
</ul>
Here is a sample of what you could do: repro on Stackblitz
And in case stackblitz is not working, here is the code :
.html :
<ul *ngFor="let chunk of displayedValues">
<li>
<span *ngFor="let value of chunk">{{value}}:00 - </span>
</li>
</ul>
.ts :
import { Component, OnInit } from '#angular/core';
import { getAttrsForDirectiveMatching } from '#angular/compiler/src/render3/view/util';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
values = [13,14,15,18,19,22,23,24];
displayedValues = [];
ngOnInit(){
this.customChunk();
}
customChunk(){
let array = [];
this.values.forEach(val => {
if(array.length === 0
|| val === array[array.length-1] + 1){
array.push(val);
} else {
this.displayedValues.push(array);
array = [];
}
});
// add the last chunk
this.displayedValues.push(array);
}
}
The idea is to rework your array into an array of chunk made by numbers that follow themselves. Then you just have to do a loop inside a loop to display your values.

change background color based on response attributes Angular

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>

Angularjs2 show json like tree

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" ] } } }

Angular 2 dynamic expendable nested lists

I have this dynamic list created with ngFor. When I click on item I want to expand it with new dynamic list, but only for that item. In my following code it expends for every item in the first list. I understand why that is happening, but I don't have ideas how to solve it.
Here is my code
<ul *ngFor="let p of portList">
<li (click)="setONUList(p.name)" id="{{ p.name }}"><img src="app/resources/{{ p['oper-status'] }}.png" class="myimage"/>{{ p.name}}</li>
<ol *ngFor="let onu of portONUList">
<li><img src="app/resources/{{ onu['oper-status'] }}.png" class="myimage" />{{ onu.name}}</li>
</ol>
</ul>
Any ideas how to solve this would be very helpful.
From what I understand, the subarray is the same which is shown for all your items, so there is no relation between the nested array and the outer array.
My suggestion would actually be to add a new property in your array, e.g expanded... so e.g your outer array would look like:
portList = [{id:1,name:'one',expanded:false},{id:2,name:"two",expanded:false}];
And then your HTML:
<ul *ngFor="let p of portList">
<li (click)="expand(p)">{{ p.name}}</li>
<div *ngIf="p.expanded">
<ol *ngFor="let onu of portONUList">
<li>{{ onu.name}}</li>
</ol>
</div>
</ul>
And on click, toggle the expanded property:
expand(p: any) {
p.expanded = !p.expanded;
}
Of course if you want to have a "quick" solution you could rely on HTML5 with no need of the new property:
<details *ngFor="let p of portList">
<summary>{{p.name}}</summary>
<ul *ngFor="let onu of portONUList">
<li>{{ onu.name}}</li>
</ul>
</details>
Here's a plunker with both options.
There should be a relation between parent and childlist and the list should be in json format. Refer below code
<ul>
<li ng-repeat="item in parent" ng-click="showChilds(item)">
<span>{{item.name}}</span>
<ul>
<li ng-repeat="subItem in item.subItems" ng-show="item.active">
<span>{{subItem.name}}</span>
</li>
</ul>
</li>
</ul>
Sample JSON FORMAT
let parent= [
{
name: "Item1",
subItems: [
{name: "SubItem1"},
{name: "SubItem2"}
]
},
{
name: "Item2",
subItems: [
{name: "SubItem3"},
{name: "SubItem4"},
{name: "SubItem5"}
]
},
{
name: "Item3",
subItems: [
{name: "SubItem6"}
]
}
];