I have been trying to develop a todo list project. I have two components itemList and item in my project. The item List component gets the input value for the todolist and displays it in the item component.
The item list component holds an array of objects, with a checkbox. What I have been trying to do, is to set a button filter for this list based on the checkbox. So when the button (display checked) is clicked, the list should display only the items that were checked in the checkbox.
I have attached the stackblitz code here: code available here
Below are the codes I tried:
item-component.html
<div >
<div
[style.backgroundColor]="IsChecked ? 'grey' : '#ff6165'"
>
<div>
<mat-checkbox
color="secondary"
[(ngModel)]="IsChecked"
(change)="onChange($event, value.task)"
></mat-checkbox>
</div>
</div>
<div >
<div [ngClass]="{ 'line-through': value.task }">
{{ value.task | uppercase }}
</div>
</div>
<div >
<Matbutton mat-icon-button [matMenuTriggerFor]="menu">
<mat-icon>more_vert</mat-icon>
</Matbutton>
<mat-menu #menu="matMenu">
<button mat-menu-item (click)="removeTask($event)">
<mat-icon >delete</mat-icon>
<span>remove</span>
</button>
</mat-menu>
</div>
</div>
</div>
item.component.ts
export class ItemComponent implements OnInit {
@Input()
value: any;
IsChecked: boolean;
@Output()
checkTask = new EventEmitter<any>();
constructor() {
this.IsChecked = false;
}
ngOnInit(): void {}
onChange($event: any, name: any) {
if ($event.checked) {
this.checkTask.emit(this.value);
}
else {
this.removeCheck.emit(this.value)
console.log('the task is removed');
}
}
}
item-list.component.html
<div>
<mat-form-field appearance="outline">
<input
matInput
placeholder="Add a Task"
(keyup.enter)="addTask()"
autocomplete="off"
[formControl]="nameControl"
/>
</mat-form-field>
<button (click)="displaylist()">Display Checked</button>
</div>
<ng-container *ngIf="filteredData$ | async as data">
<div
cdkDropList
(cdkDropListDropped)="drop($event, data)"
>
<app-item
[value]="value"
*ngFor="let value of data; index as index"
(inputDataChange)="removeTask(data, index)"
(checkTask)="addCheckedTask($event, data)"
(removeCheck)="removeCheckedTask($event,data)"
cdkDrag
>
</app-item>
</div>
</ng-container>
item-list.component.ts
public arrayChecked: TaskType[] = [];
addCheckedTask($event: any, data: any): void {
this.arrayChecked.push($event);
console.log('the task is added', this.arrayChecked);
}
displaylist(){
const selectList$ = this.arrayChecked.map((checked, index) => checked ?
this.arrayChecked[index] : null).filter(value => value !== null);
console.log("DisplayChecked",selectList$);
}
removeCheckedTask($event:any, data:any){
const index = this.arrayChecked.findIndex(list => list.task);
this.arrayChecked.splice(index, 1);
console.log(this.arrayChecked);
}
In the above code, the item-list component has a button "Display checked". This is where I tried to make a array of objects that were checked using a function. The log shows , the array holds only the checked items, but I dont know how to display only the checked items inside the component. I have also attached the stackblitz link above. Can someone show me how to display only the checked items in the list when the button is clicked. Thank you in advance!
CodePudding user response:
Since your list is driven by filteredData$
in the template, you need to update it with selectList$
, that holds all the checked items.
item-list.component.ts:
displaylist(){
const selectList$ = this.arrayChecked.map((checked, index) => checked ? this.arrayChecked[index] : null)
.filter(value => value !== null);
console.log("DisplayChecked",selectList$);
// add this code
if (selectList$) {
this.filteredData$ = new Observable((subscriber) => {
subscriber.next(selectList$ as TaskType[])
});
}
}
I have also added a 'Reset' button in To Do section of the Demo, so you can test the case of undoing 'Display Checked'. For this, I created a re-usable function initlist()
, called it in ngOnInit()
and attached to 'Reset' button's click event.
item-list.component.ts:
export class ItemListComponent implements OnInit {
...
...
...
ngOnInit(): void {
this.initlist();
}
...
...
initlist() {
if (this.initialData$) {
this.filteredData$ = combineLatest([
this._homeService.searchData$,
this.initialData$,
]).pipe(
map(([searchValue, dailyList]) =>
this._filterData(searchValue, dailyList)
)
);
}
}
}