
Adding exercises using ExerciseNav
To add exercises to the workout we are building, we just need to import WorkoutBuilderService and ExercisePlan, inject WorkoutBuilderService into the LeftNavExercisesComponent, and call its addExercise method, passing the selected exercise as a parameter:
constructor( public workoutService:WorkoutService, public workoutBuilderService:WorkoutBuilderService) {} . . . addExercise(exercise:Exercise) { this.workoutBuilderService.addExercise(new ExercisePlan(exercise, 30)); }
Internally, WorkoutBuilderService.addExercise updates the buildingWorkout model data with the new exercise.
The preceding implementation is a classic case of sharing data between independent components. The shared service exposes the data in a controlled manner to any component that requests it. While sharing data, it is always a good practice to expose the state/data using methods instead of directly exposing the data object. We can see that in our component and service implementations too. LeftNavExercisesComponent does not update the workout data directly; in fact, it does not have direct access to the workout being built. Instead, it relies upon the service method, addExercise, to change the current workout's exercise list.
Since the service is shared, there are pitfalls to be aware of. As services are injectable through the system, we cannot stop any component from taking dependency on any service and calling its functions in an inconsistent manner, leading to undesired results or bugs. For example, WorkoutBuilderService needs to be initialized by calling startBuilding before addExercise is called. What happens if a component calls addExercise before the initialization takes place?