new retrieved list of the selected item from a list - html

I have a list which retrieves data from an object from backend, and after selecting an item from that list, it should display its items but i don't know how to render that in html or in rxjs.
Here is my current state after selecting the item Test1 from the list, it retrieve its inner items that are info 1 and info 2.
List:
List: Array(2)
0: {name: "Test1", item: Array(2)}
1: {name: "Test2", item: Array(1)}
length: 2
__proto__: Array(0)
selectedItemData: Array(2)
0: {name: "info 1", item: Array(1)}
1: {name: "info 2", item: Array(4)}
But the list doesn't change, even though everything works concerning the retrieving part of each selected item.
Here is my html :
<ul class="unstyled" *ngFor="let i of (listObservable$|async).list.List">
<li><a (click)="selected(i.name)">{{i.name}}</a></li>
</ul>

When using the async pipe it is best to us an ngIf and map it to a view variable so you only render the element once the observable has emitted.
<ng-container *ngIf="listObservable$ | async as listObj">
<ul class="unstyled" *ngFor="let i of listObj.list.List">
<li><a (click)="selected(i.name)">{{i.name}}</a></li>
</ul>
</ng-container>

Related

How I can parse object to array in angular?

I get an object from an array of elements, and I need to parse it as an array and display it as a list, can you tell me how to do this? I only know how to handle requests.
html:
<ul *ngFor="let filtered of reposFiltered">
<li>
{{filtered.name}}
{{filtered.description}}
{{filtered.language}}
{{filtered.html}}
</li>
</ul>
.ts:
// Required data
selectRepo(data){
this.reposFiltered = data;
console.log(data)
}
massive with objects:
0: cu {name: "30daysoflaptops.github.io", description: null, language: "CSS", html: "https://github.com/mojombo/30daysoflaptops.github.io"}
1: cu {name: "asteroids", description: "Destroy your Atom editor, Asteroids style!", language: "JavaScript", html: "https://github.com/mojombo/asteroids"}
etc
If you only wish to see the data in the rows you could use the following code:
// the data
const data = [
{name: "30daysoflaptops.github.io", description: null, language: "CSS", html: "https://github.com/mojombo/30daysoflaptops.github.io" },
{name: "asteroids", description: "Destroy your Atom editor, Asteroids style!", language: "JavaScript", html: "https://github.com/mojombo/asteroids"}
];
// Required data
selectRepo(data){
this.reposFiltered = data.map(row => Object.values(row));
}
//html
<!-- iterate through all data rows -->
<ul *ngFor="let row of reposFiltered">
<!-- iterate through all values -->
<li *ngFor="let value of row">
{{ value }}
</li>
</ul>
To iterate over the properties on an object you need to use the https://angular.io/api/common/KeyValuePipe
something like this:
<ul *ngFor="let filtered of reposFiltered | keyvalue">
<li>
{{filtered.value.name}}
{{filtered.value.description}}
{{filtered.value.language}}
{{filtered.value.html}}
</li>
</ul>
If you need to access the key:
{{filtered.key}}
This code is useful for debugging:
{{filtered.key | json}}
{{filtered.value | json}}

How to bind a single element from a model object in angular in a template

Can someone give me a clue, how to bind a variable value from a .model created?
I have used ng for in a div, then I can interpolate values from a .model.ts using:
ngFor let list of lists
then i {{name.list}}
But in other div, I just can show a dynamic name of a .model.ts, like name.list.
How can I do this?
Thanks
If you have in your component some data like:
usersList = [
{ name: "Michael", id: 1 },
{ name: "Linda", id: 2 }
];
In your template html you should do something like this:
<h2>List of users</h2>
<ul *ngIf="userList.length">
<li *ngFor="let user of userList">
Hello {{user.name}} (id: {{user.id}})
</li>
</ul>
<div *ngIf="!userList.length">No users</div>

looping through JSON Keys and values

it seems quite simple but some how i can't loop through the items as i would like to
i have this json object
"meters":{
"Rozvadec M11":{
"0":{
"Name":"m11-mcu13_sm114",
"Title":"Svarovaci centrum Flexarc",
"Parent":"m11-mcu13",
"Status":"Running",
"State":false
},
"1":{
"Name":"m11-mcu13_sm115",
"Title":"Brousici centrum Solicad",
"Parent":"m11-mcu13",
"Status":"Running",
"State":false
}
},
"Rozvadec R1-L":{
"0":{
"Name":"r1-l-mcu1_sm100",
"Title":"Amada NCT1",
"Parent":"r1-l-mcu1",
"Status":"Device unavailable",
"State":false
},
"1":{
"Name":"r1-l-mcu1_sm101",
"Title":"Amada 1",
"Parent":"r1-l-mcu1",
"Status":"Device unavailable",
"State":false
},
"2":{
"Name":"r1-l-mcu1_sm102",
"Title":"Amada 2",
"Parent":"r1-l-mcu1",
"Status":"Device unavailable",
"State":false
}
},
what i am trying to do is to loop through all meters to have a list of
"Rozvadec M11"
"Rozvadec R1-L"
and under each have a list of different smartmeters names
i have this in ts
let list = this.http.get('EndpointURL');
list.subscribe (
(response: Response)=>
{this.meters.push(response);
console.log(this.meters);
})
and this in html (i was trying to loop only through the meters first before i nest the for loops)
<ul *ngFor="let meter of meters">
<li>{{ meter}}</li>
</ul>
You have most of your code right but the ngFor is not used in that way. The html tag with the ngFor is what will be repeated and you that's why you should use it in the li instead of the list tag ul. It would be like this for you:
<ul>
<li *ngFor="let meter of meters">
{{meter}}
</li>
<ul>
This exact example is covered here in the docs.
EDIT: If you want to access the key of your list, in this SO answer you can see the new way in Angular6 to retrieve it. It will end up like this for your example:
<ul>
<li *ngFor="let meter of meters | keyvalue">
{{meter.key}}
</li>
<ul>
You can read more about the keyValuePipe in the docs.

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

Build category menu with angularJS

I'm having problem with logic of building category menu with AngularJS
I wan't to print all categories with parent category id 0. Once this is done i wan't to print all sub categories which belong to its parent category.
End category menu should look like this:
- Audio, video & photo
--- Music players
--- Musical instruments
--- ...
--- Rest
- Cars
--- Whole cars
This is how my categories object looks like
0: Object
alias: "audio-video-and-photo"
category: "AUdio, video & photo"
id_category: "1"
parrent: "0"
__proto__: Object
1: Object
alias: "music-players"
category: "Music players"
id_category: "2"
parrent: "1"
__proto__: Object
2: Object
alias: "musical-instruments"
category: "Musical instruments"
id_category: "3"
parrent: "1"
__proto__: Object
3: Object
alias: "music-accessories"
category: "Music accessories"
id_category: "4"
parrent: "1"
__proto__: Object
4: Object
alias: "hi-fi"
category: "Hi-Fi"
id_category: "5"
parrent: "1"
__proto__: Object
5: Object
alias: "home-cinema"
category: "Home cinema"
id_category: "6"
parrent: "1"
__proto__: Object
6: Object
alias: "tv"
category: "TV's"
id_category: "7"
parrent: "1"
__proto__: Object
7: Object
alias: "rest"
category: "Rest"
id_category: "8"
parrent: "1"
__proto__: Object
8: Object
alias: "cars"
category: "Cars"
id_category: "9"
parrent: "0"
__proto__: Object
9: Object
alias: "whole-cars"
category: "Whole cars"
id_category: "10"
parrent: "9"
__proto__: Object
....
And this is how my HTML looks like
<div ng-repeat="c in categories track by $index">
<h4 ng-if="c.parrent == 0">{{c.category}}</h4>
<ul>
<li>{{c.category}}</li>
</ul>
</div>
End HTML should look similar to this
<div>
<h4>Audio, video photo</h4>
<ul>
<li>Music players</li>
<li>Music instruments</li>
<li>Music accessories</li>
<li>Hi-fi</li>
<li>Home cinema</li>
<li>Rest</li>
</ul>
<h4>Cars</h4>
<ul>
<li>Whole cars</li>
<li>Car accessories</li>
<li>Car parts</li>
<li>Rest</li>
</ul>
</div>
I hope you guys can help. Thanks in advance.
You can use ng-if to handle like this. Here is a solution with a nested ng-repeat.
<div ng-repeat="c in categories track by $index">
<h4 ng-if="c.parrent == 0">{{c.category}}</h4>
<ul ng-if="c.parrent != 0"
ng-repeat="sub_c in categories track by $index">
<li ng-if="sub_c.parrent == c.id_category">
{{sub_c.category}}
</li>
</ul>
</div>
Note that it will be better to organize your data before rendering or using a helper method to filter sub-category items. This will be efficient than do ng-repeat twice.
Update 1:
As requested, I post the idea how to organize data before rendering. I'll use with the library underscore (or lodash).
function build_category(categories) {
var result = _.filter(categories, function(c) {
return c.parrent == 0;
});
_.forEach(result, function(c) {
c.sub_categories = _.filter(categories, function(c2) {
return c2.parrent == c.id_category;
});
});
return result;
}
var grouped_categories = build_category(categories);
<div ng-repeat="c in grouped_categories track by $index">
<h4>{{c.category}}</h4>
<ul ng-if="c.sub_categories"
ng-repeat="sub_c in c.sub_categories track by $index">
<li>{{sub_c.category}}</li>
</ul>
</div>
If you have a large category, you will see some performance difference.