Ionic - HTML list with parents and child elements - ionic-framework

I have data in array where every element represents parent object, and every parent object has items array, whose elements are children. I have to generate on HTML parents list + nested children list under every parent. Every child element is clickable (navigates to another page). Something like on image. Any help here? I can use *ngFor to iterate first level elements (parents) and use ion-list and ion-item but how to nest children?

You can basically do a nested *ngFor.
Example data:
var categories = [
{
"name": "Category 1",
"items": [
"item1"
"item2"
]
}
];
Example template:
<div *ngFor="let category of categories">
<h2>{{category.name}}</h2>
<ion-list>
<ion-item *ngFor="let item of category.items">{{item}}</ion-item>
</ion-list>
</div>
At the top-level you iterate your categories, and for every single category, you iterate its items.

Related

Ionic 5 Directory tree dynamically

I have done a simple JavaScript file browser which shows the contents of each directory, loading the subdirectory contents from the backend using an AJAX request when the directory name is clicked. Loading the full tree is out of the question. The directory contents are sent in JSON. The directory is something like the one below and cannot be loaded as a whole recursively due to the number of directories and files. The (imaginary) directory structure is simple, but it can have several nested levels:
docs
assemblies
2019-07
doc-6811.txt
instructions-6811.pdf
2019-08
doc-7012.txt
instructions-7012.pdf
...
invoices
2019-07
invoice-6811.pdf
2019-0
invoice-7012.pdf
tickets
2019-07
ticket-98141.txt
The items for each directory are in an array of JS Objects:
[{
name: '2019-07',
isDirectory: true,
fullPath: "/mnt/samba/docs/assemblies/2019-07"
},
{
name: '2019-08',
isDirectory: true,
fullPath: "/mnt/samba/docs/assemblies/2019-08"
} ...
]
There are files as well, of course, but they are not a problem. Now I need to do the same in Ionic but, I am totally lost with the starting point. The top directory renders nicely and the current simple template (I call it a template) is something like this:
<ion-content>
<ion-list>
<ion-item-sliding *ngFor="let d of directories">
<ion-item (click)="openFolder(d)"> <!-- just an example call --->
<ion-icon name="folder" slot="start" *ngIf="d.isdirectory"></ion-icon>
<ion-icon name="triangle" slot="start" *ngIf="!d.isdirectory"></ion-icon>
<ion-label text-wrap>
{{ d.name }}
<p>{{ d.fullPath }}</p>
</ion-label>
<!-- THIS is where the directory contents should appear using
the same structure as this template -->
</ion-item>
</ion-item-sliding>
</ion-list>
</ion-content>
What the code should do is simply fetch the data from the backend and bind it to an array variable, which would then be rendered below to the spot given above. Can this be done in Angular, or is using some other framework any easier? I assume there is a component approach of some sort available, but it should be totally dynamic and fetching plus rendering of one directory should take place per request.
Fetching the directories is a simple task and I get the array just fine. However, I have not been able to get any rendering done yet. Any alternatives and/or pointers are welcome.
Your JSON has to be a recursive JSON. By that I mean,
{ "items": [
{
"name": "ABC1",
"isDirectory": true,
"fullPath": "/mnt/samba/docs/assemblies/2019-07",
"children":[
{
"name": "ABC11",
"isDirectory": true,
"fullPath": "/mnt/samba/docs/assemblies/2019-08"
},
{
"name": "ABC12",
"isDirectory": true,
"fullPath": "/mnt/samba/docs/assemblies/2019-08"
}
]
},
{
"name": "ABC2",
"isDirectory": true,
"fullPath": "/mnt/samba/docs/assemblies/2019-08"
}
]
}
If it can be this way, you can handle the same using recursive ng-template
A sample of the same is as given in this link.
Click here to view the link.
A little Google on recursive ng-template can also help. :)
I sincerely hope that this helps.

how do I rendering multiple components using xstreamjs

Suppose, I want to render 3 buttons which are mapped from Array
export const homePage = soruces => {
const array$ = xs.fromArray([1,2,3])
return {
DOM: array$.map(e => {
return <button id={e}>click</button>
})
};
};
but I only get the lastest button which has id of 3
<div id="app">
<button id="3">click</button>
</div>
how do i get all the buttons rendered like this using xstream or rxjs
<div id="app">
<button id="1">click</button>
<button id="2">click</button>
<button id="3">click</button>
</div>
That depends a bit on what you want to achieve. The code you have there basically says: "I get three pieces of data, each at some arbitrary point of time" (because fromArray basically takes the data from the array one by one and puts it into the stream.
If you now what to collect the data over time, you can add fold((buttons, newButton) => buttons.concat(newButton), []).
If however you just happen to have three poeces of data, that always should be three buttons, do not use fromArray but the normal Array.map. You can then use xs.of to emit the three buttons at once (compared to one by one in the first part)

Ionic 3 : How to display array of arrays?

I have a following consoled list of array how can i display the list?
I tried
this.item = this.data.["0"] // this is throwing an error
is there any other workaround to achieve this?
You have an array in an array. To display the list, you have to loop over the items in the array. Because your output is an array in an array, you can start the loop from the first element of the outer array.
Example:
<ion-list>
<button ion-item *ngFor="let item of items[0]">
{{ item.item_id }}
</button>
</ion-list>
Assuming your parent array is called data you can access the first element by using this.data[0]. You can also do other things such as loop over the items in the array, etc.

Problem refreshing ion-select-options when data is updated

I am developing an Ionic application (v.4 final release)...
My problem:
I have an <ion-select> and this select has a list of <ion-select-option>, and this options was created doing *ngFor... the problem is: when I change the array, remove an element, for example, the ionc-select-options cannot re-render the new status of this array.
<ion-select>
<ion-select-option *ngFor="let question of questions">{{ question }}</ion-select-option>
</ion-select>
(I am updating questions array)
Any ideas?
UPDATE:
If a put the *ngFor in other element, like a div, it works fine:
example:
(It is no updating when I delete the first element)
<ion-select>
<ion-select-option *ngFor="let question of questions">{{ question }}</ion-select-option>
</ion-select>
<button (click)="deleteFirst()>Delete first!</button>
(It is updating when I delete the first element)
<div *ngFor="let question of questions"></div>
<button (click)="deleteFirst()>Delete first!</button>
class MyComponent() {
public questions = ['question1','question2','question3'];
deleteFirst() {
this.questions.splice(0, 1);
}
}
You are using splice method alters the content of an array but doesn't change its reference.
In other words, you should work with immutable objects/Array, and create new instances when you need to make a change.
In your case :
deleteFirst() {
if (this.questions.length) {
this.questions = this.questions.filter((el, index) => index > 0);
}
}
Here filter returns a new reference to an array containing objs that fulfill a condition

Could not check the data in array of array

I need to check that my app has the data that i give in my array
i have a html like this
<ion-card class="card1">
{{name}}
</ion-card>
<ion-card class="card2" *ngfor="prod of orderlist>
{{products}}
</ion-card>
In my e2e
describe('module',()=>{
it('should have the same data in list array'),() => {
var quantity = element(by.css('.card2');
expect(quantity.getText()).toContain(list[0].product[0].check)
});
//my array
var list = [{ name : 'yoke',
product :[{check :'no' },
{check :'no' }]
}];
});
what i need is that my app has a field with a value "no", I need to check it weather that data is present in my card, in the same way i have a big sized array
while testing this in protractor it says that "Cannot find name 'product'. (2304)"