Skip to content
View lessons Login
3d cartoon hands holding a phone

Unlock full course by purchasing a membership

Creating Checklist Items

Creating Checklist Items

The path we take to implement this feature is going to look pretty similar to creating the checklists, and it will be the same with just about any feature we would implement.

Create the ChecklistItem Interface

We are creating a new entity in our application now — items that belong to a specific checklist. We are first going to define a new type that represents this entity in the application.

import { RemoveChecklist } from './checklist';
export interface ChecklistItem {
id: string;
checklistId: string;
title: string;
checked: boolean;
}
export type AddChecklistItem = {
item: Omit<ChecklistItem, 'id' | 'checklistId' | 'checked'>;
checklistId: RemoveChecklist;
};
export type EditChecklistItem = {
id: ChecklistItem['id'];
data: AddChecklistItem['item'];
};
export type RemoveChecklistItem = ChecklistItem['id'];

In general, this is the same idea as our Checklist type but there is some extra weirdness happening here. First of all, our ChecklistItem type is just different — as well as the title we also have a checklistId to indicate what Checklist it belongs to, and a checked to indicated whether it is currently in the completed state or not.

We have the same style of types for adding and editing as we did with the Checklist but for this one we also have our checklistId property based on whatever the RemoveChecklist type is from our Checklist interfaces.

We could just give checklistId a type of string which would match the id from our Checklist interface. This is just a bit safer because if we ever update the type of the id in Checklist we won’t need to remember to change this too.

Creating the Checklist Item service

Our checklist service was created in the shared/data-access folder because it is used by multiple features in the application. However, our ChecklistItemService will only be used by the checklist item feature — so, we will store it inside of the checklist/data-access folder.

import { Injectable, computed, signal } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { Subject } from 'rxjs';
import {
AddChecklistItem,
ChecklistItem,
} from '../../shared/interfaces/checklist-item';
export interface ChecklistItemsState {
checklistItems: ChecklistItem[];
}
@Injectable({
providedIn: 'root',
})
export class ChecklistItemService {
// state
private state = signal<ChecklistItemsState>({
checklistItems: [],
});
// selectors
checklistItems = computed(() => this.state().checklistItems);
// sources
add$ = new Subject<AddChecklistItem>();
constructor() {
this.add$.pipe(takeUntilDestroyed()).subscribe((checklistItem) =>
this.state.update((state) => ({
...state,
checklistItems: [
...state.checklistItems,
{
...checklistItem.item,
id: Date.now().toString(),
checklistId: checklistItem.checklistId,
checked: false,
},
],
}))
);
}
}

Again, nothing really new here — this is almost identical to what we did with the ChecklistService. Our reducer is a bit more complicated so let’s talk through what is happening here:

this.state.update((state) => ({
...state,
checklistItems: [
...state.checklistItems,
{
...checklistItem.item,
id: Date.now().toString(),
checklistId: checklistItem.checklistId,
checked: false,
},
],
}))

We are trying to update the checklistItems state. This service will contain an array of all items for all checklists. We add a checklistId to each item to tell which checklist it belongs to.

When updating our state, we first copy all of the existing checklistItems into the new array:

...state.checklistItems,
STANDARD STANDARD

Thanks for checking out the preview of this lesson!

You do not have the appropriate membership to view the full lesson. If you would like full access to this module you can view membership options (or log in if you are already have an appropriate membership).