Reputation: 6951
I am developing an anglular application and I can say I am kind of new at angular. In my application I am binding data from server via httpclient with an observable array to a basic list like below. And I add a new item to list at different component. The both list component and adding new item components are at same page.
I have no problem with binding data and adding new one. I am getting problem after I add a new item. After I add new item to data source of list, the whole component getting refresh; but I don't want this, I want to add new element without refreshing list.
The simplified codes is here. My component that contain list:
export class GroupSetupComponent implements OnInit {
dataSet$: Observable<Group[]>;
constructor (private groupService : GroupService) {}
ngOnInit(): void {
this.getGroups();
}
getGroups() {
this.dataSet$ = this.groupService.getGroups();
}
refreshGroupList(group: Group) {
if(group) {
// I have tried getting all list from database again
// this.getGroups();
// than I tried to add new item to existing observable array
this.dataSet$ = this.dataSet$.
pipe(
map(data =>
{
data.push(group);
return dataSet;
}));
}
}
}
And component template:
<div *ngIf="dataSet$ | async as resultSet;">
<mat-card>
<mat-card-content>
<mat-selection-list>
<mat-list-option *ngFor="let item of resultSet;" [value]="item.id" [disableRipple]="true">
{{item.name}}
</mat-list-option>
</mat-selection-list>
</mat-card-content>
</mat-card></div>
The refreshGroupList function is triggering from child component after new item added to database and getting success message from api.
I want to ask , the way I am doing is right or not? If not what is the efficient way to doing this kind of crud operations on a list?
Upvotes: 1
Views: 4565
Reputation: 11360
You can add this to your component
byId(index, item) {
return item.id;
}
and modify the ngFor
<mat-list-option *ngFor="let item of resultSet; trackBy: byId" [value]="item.id" [disableRipple]="true">
{{item.name}}
</mat-list-option>
By providing a trackBy key, angular will check each item and do the diff by ID instead of refreshing entire array. If you open up developer tool and inspect element you will notice only newly added item will get the dom update.
UPDATE---- You can try change your implementation like below, so you stream reference remain unchanged, see if that solves the problem
dataSet$=new BehaviorSubject([])
ngOnInit(): void {
this.getGroups().subscribe(group=>dataSet$.next(group));
}
refreshGroupList(group){
this.dataSet$.next(this.dataSet$.value.concat(group))
}
Upvotes: 3
Reputation: 266
You can set on component ChangeDetection: OnPush
and manualy tell when component should be refreshed by using ChangeDetecionRef service and method markToCheck()
.
Upvotes: 0