Skip to content

Instantly share code, notes, and snippets.

@Armenvardanyan95
Created April 8, 2025 10:40
Show Gist options
  • Save Armenvardanyan95/f0b58ca594e2f11beeca4ae2fbad36a7 to your computer and use it in GitHub Desktop.
Save Armenvardanyan95/f0b58ca594e2f11beeca4ae2fbad36a7 to your computer and use it in GitHub Desktop.
export class TodoStore {
readonly #todoService = inject(TodoService);
query = signal('');
todosResource = httpResource(() => ({
url: '/api/todos',
params: { q: this.query() },
method: 'get',
}),
// use a default value and parsing with Zod
{defaultValue: [], parse: todoListSchema.parse});
// computed properties for convenience
todos = computed(() => this.todosResource.value());
loading = computed(() => this.todosResource.isLoading());
status = computed(() => this.todosResource.status());
error = computed(() => this.todosResource.error());
search(query: string) {
this.query.set(query);
}
// all of these will be way simpler when we have HTTP mutation reactive APIs
addTodo(todo: Todo) {
// you can do an optimistic update
this.todosResource.update(todos => [...todos, todo]);
// or you can refetch after update success
this.#todoService.addTodo(todo).subscribe(
() => this.todosResource.reload(),
);
}
deleteTodo(id: string) {
this.todosResource.update(
todos => todos.filter(todo => todo.id !== id)
);
this.#todoService.deleteTodo(id).subscribe(
() => this.todosResource.reload(),
);
}
}
// in some HTML:
<div>
<input [(ngModel)]="todoStore.query" />
@for (todo of todoStore.todos; track todo.id) {
<span>
{{todo.title}}
<button (click)="todoStore.deleteTodo(todo.id)">
Delete
</button>
</span>
}
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment