angularrxjsobservablerxjs-observablesasync-pipe

How to modify data in an angular component when using async pipe


I have an Angular 18 component that receives an observable, which I render on the page using an async pipe. I want to be able to modify the data within this component and then press a "Save" button.

Before The save button is pressed, how do I edit the values within this component? I am somewhat new to working with async pipes and normally I would have just subscribed within the component, but I am trying to stick to best practices and avoid subscribing where I can, instead have the async pipe take care of this.

Here's what I am doing, and

export class TimesheetSelectedDayComponent {
  private readonly activatedRoute = inject(ActivatedRoute);
  private readonly timesheetService = inject(TimesheetService);

  //whenever the route params OR the selected timesheet changes...
  selectedDay$ = combineLatest({
    params$: this.activatedRoute.paramMap,
    timesheet$: this.timesheetService.selectedTimesheet$,
  }).pipe(
    switchMap((results) =>
      //now get the matching day from the timesheet
      of(results.timesheet$?.days.find((d) => d.date.dayOfWeek === results.params$.get('dayOfWeek'))),
    ),
  );

  addAbsence(absence: ITimesheetAbsence): void {
    //How do I add this to the selectedDay.absences array?
  }

  removeAbsence(absenceTimeEntity: ITimesheetAbsence): void {
    //How do I remove this from the selectedDay.absences array?
  }
}
@if (selectedDay$ | async; as selectedDay) {
  <h5 class="card-header">{{ selectedDay.date }}</h5>
  <div class="card-body">
    <ul class="list-group">
        <li class="list-group-item">
          <app-time-entity-editor name="Work Day" [timeEntityObject]="selectedDay.workDay" />
        </li>
        <li class="list-group-item">
          <app-time-entity-editor name="Lunch" [timeEntityObject]="selectedDay.lunch" />
        </li>
        @for (absence of selectedDay.absences; track $index) {
          <li class="list-group-item">
            <app-time-entity-editor
              isRemovable="true"
              [name]="absence.name"
              [timeEntityObject]="absence"
              (removeClick)="removeAbsence($event)"
            />
          </li>
        }
      </ul>

      <app-absence-selector class="d-block mt-2" (selectAbsence)="addAbsence($event)" />
    </div>

    <button type="button" class="btn btn-outline-success btn-lg">Save</button>
  </div>
} @else {
  <h5 class="card-header">&nbsp;</h5>
  <div class="card-body">
    <app-spinner />
  </div>
}

Basically I want to have the ability to make changes to the data in my component before I save the changes and make the observable react in other areas where it is subscribed to


Solution

  • Just pass selectedDay to methods. For removeAbsence it is easier to pass index instead of item itself.

    addAbsence(day: DayOfWeek, absence: ITimesheetAbsence): void {
      day.absences.push(absence);
    }
    
    removeAbsence(day: DayOfWeek, absenceIndex: number): void {
      day.absences.splice(absenceIndex, 1);
    }