Reputation: 528
here what my requirement is :-
when ever i click on the parent its child elements has also get selected and in that also we can deselect what ever we dont want. And on button click the we have to get the selected parent & children names as object
what i did till now :-
i created a list of parents and children and supplied checkbox for the parent and getting the parents values after check n uncheck and getting the value
im stuck how can i select the children in that parent and get values of both parent and children
below is my code
.ts
@ViewChildren('myItem') item;
selectedIds = [];
display:any;
data:any;
ngOnInit(){
// dynamic json
this.data = {
"info": {
"laptop": {
},
"config": {
"properties": {
"ram": {
},
"processor": {
},
"hdd": {
}
}
},
"link": {
},
"name": {
},
"company": {
"properties": {
"model": {
},
"maker": {
"type": "integer"
},
"country": {
"type": "text"
},
"enterprise": {
}
}
}
}
};
// varible
this.display = this.data['info'];
console.log(this.display);
}
change(data,event){
if (event.target.checked === true) {
this.selectedIds.push({id: data, checked: event.target.checked});
console.log('Selected data ', JSON.stringify(this.selectedIds));
}
if (event.target.checked === false) {
this.selectedIds = this.selectedIds.filter((item) => item.id !== data);
}
}
getData(){
const filtered = this.selectedIds.filter(item => item.id)
console.log(JSON.stringify(filtered));
}
.html code
<ul class="list-group" *ngFor="let parent of display | keyvalue">
<li class="list-group-item"> <input type="checkbox" [value]="parent.key" [(ngModel)]="parent.check" #myItem (change)="change(parent.key,$event)">{{parent.key}}</li>
<ng-container *ngIf="parent.check && parent.value.hasOwnProperty('properties')">
<ul *ngFor="let child of parent.value.properties | keyvalue">
<li>
{{child.key}}
</li>
</ul>
</ng-container>
</ul>
<hr>
<button class="btn btn-primary"(click)="getData()">get Data</button>
my stackblitz link
https://stackblitz.com/edit/angular-8vqwsc
Upvotes: 0
Views: 1450
Reputation: 58074
the only thing you need is pass to your function the "children"
(change)="change(parent.key,parent.value.properties,$event)"
then in your function change becomes like
change(data, children, event) {
if (event.target.checked === true) {
this.selectedIds.push({ id: data, checked: event.target.checked });
for (let child in children) {
this.selectedIds.push({ id: child, checked: event.target.checked });
}
}
if (event.target.checked === false) {
this.selectedIds = this.selectedIds.filter((item) => item.id !== data);
for (let child in children) {
this.selectedIds = this.selectedIds.filter((item) => item.id !== child);
}
}
There are a problem that is show the selected values. For this you need make a function
isChecked(child) {
let item = this.selectedIds.find(x => x.id == child.key)
return item ? item.checked : false
}
And add (click) to the "children" to change the this.selected
<ul *ngFor="let child of parent.value.properties | keyvalue">
<li>
<input type="checkbox" [checked]="isChecked(child)" (change)="change(child.key,null,$event)"/>
{{child.key}}
</li>
</ul>
But I think that there're a better way to do the things. Imagine that your data becomes
this.data2 =[
{
"id":"laptop","checked":false
},
{"id":"config","checked":false,"properties": [
{"id":"ram","checked":false},
{"id":"processor","checked":false},
{"id":"ram","checked":false}
]
},
{"id":"link","checked":false},
{"id":"name","checked":false},
{"id":"company","checked":false,"properties":[
{"id":"model","checked":false},
{"id":"maker","checked":false},
{"id":"country","checked":false},
{"id":"enterprise","checked":false}
]}
]
(I put checked property, but it's not necesary) Your .html becomes easer
<ul *ngFor="let parent of data2">
<li><input type="checkbox" [(ngModel)]="parent.checked" (change)="changedChild(parent.checked,parent.properties)"> {{parent.id}}
<ng-container *ngIf="parent.checked">
<ul *ngFor="let child of parent.properties">
<li>
<input type="checkbox" [(ngModel)]="child.checked" />
{{child.id}}
</li>
</ul>
</ng-container>
</li>
</ul>
And the function changedChild
changedChild(value,children)
{
if (children)
children.forEach(x=>x.checked=value)
}
Updated adding object to this.selectedChild the functions becomes
change(data, children, event) {
if (event.target.checked === true) {
this.selectedIds.push({ id: data, checked: event.target.checked });
for (let child in children) {
this.selectedIds[this.selectedIds.length-1][child]=event.target.checked;
}
}
if (event.target.checked === false) {
this.selectedIds = this.selectedIds.filter((item) => item.id !== data);
}
}
changeChild(parentKey,childKey,event)
{
let item:any = this.selectedIds.find(x => x.id == parentKey)
if (event.target.checked)
item[childKey]=event.target.checked;
else
delete item[childKey];
}
isChecked(parentKey,childKey) {
let item:any = this.selectedIds.find(x => x.id == parentKey)
return item ? item[childKey] : false
}
And the html
<ul class="list-group" *ngFor="let parent of display | keyvalue">
<li class="list-group-item"> <input type="checkbox" [value]="parent.key" [(ngModel)]="parent.check" #myItem (change)="change(parent.key,parent.value.properties,$event)">{{parent.key}}</li>
<ng-container *ngIf="parent.check && parent.value.hasOwnProperty('properties')">
<ul *ngFor="let child of parent.value.properties | keyvalue">
<li>
<input type="checkbox" [checked]="isChecked(parent.key,child.key)" (change)="changeChild(parent.key,child.key,$event)"/>
{{child.key}}
</li>
</ul>
</ng-container>
</ul>
Upvotes: 1