v19 launch sale ends in ... Get 25% off BUY NOW
3d cartoon hands holding a phone

Unlock full course by purchasing a membership

Lesson 9

Creating Checklist Items

STANDARD

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.

Create a file at src/app/shared/interfaces/checklist-item.ts and add the following:

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.

Create a new service at src/app/checklist/data-access/checklist-item.service.ts and add the following:

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
Key

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).