I'm using NGXS to implement the state management in my Angular project, and the states are updated by the WebSocket, a plugin of NGXS
What I implemented:
model.ts
export interface Student {
id: string;
name: string;
passed: boolean;
}
student.action.ts
export class GetStudents{
...
}
export class UpdateStatus {
static readonly type = '[Student] Update Status';
constructor( studentId: string ) {}
}
student.state.ts
...
export class StudentStateModel {
students: Student[];
}
@State<StudentStateModel>({
name: 'student',
defaults: {
students: []
}
})
@Action(GetStudents)
...
@Action(UpdateStatus)
updateStatus(
{ getState, setState }: StateContext<StudentStateModel>,
{ studentId }: UpdateStatus
) {
const students = getState().students;
const index = students.findIndex((i) => i.id === studentId);
setState((state: ApprovalStateModel) => {
state.students[index].passed = true;
return state;
});
}
...
I implement 2 components (parent and child):
1/ the parent component keeps the list of students
students$: Observable<any>; // Get list of Students from Store GetStudents
students.component.html
<div *ngFor= "let student of students$ | async">
<app-student-detail
[student] = "student"
></app-student-detail>
</div>
2/ the child component keeps the student detail, it includes an input
@Input() student: Student = null;
student-detail.component.html
<div *ngIf="student">
<p>Id: {{student.id}}</p>
<p>Name: {{student.name}}</p>
<p>Result: {{student.passed}} </p>
</div
I use the WebSocket plugin to update the student state, I sent a message
{"type": "[Student] Update Status", "studentId" : "10001"}
Result:
From the log, the state is updated successfully with passed = true for student id 10001, but from UI, the Result is not updated.
Something wrong with my implementation, any suggestion is appreciated.
Try using a state operator to update the state. For example, you could use the updateItem
to find and update an item in an array:
import { patch, updateItem } from '@ngxs/store/operators';
...
@Action(UpdateStatus)
updateStatus(ctx: StateContext<StudentStateModel>, { studentId }: UpdateStatus) {
ctx.setState(
patch({
students: updateItem<Student>(
student => student.studentId === studentId,
student => ({
...student,
passed: true
})
)
})
);
}