In the service, we are making HTTP requests to consult exercises and add new ones. For more details about Angular services, you can consult Chapter 5, Angular Services and the Singleton Pattern, and Chapter 9, Exploring Reactivity with RxJS.
However, we are experiencing an error because we are not importing the HttpClientModule module. But how can we import it if we don’t have a module in a standalone component?
In a project without modules, the import happens in the component itself; for services, we have the app.config.ts file, and we will add the import to it:
import { ApplicationConfig } from ‘@angular/core’;
import { provideHttpClient } from ‘@angular/common/http’;
export const appConfig: ApplicationConfig = {
providers: [provideHttpClient()],
};
Note that we are importing the provideHttpClient provider and not the module. This happens because this provider was created by the Angular team to handle these standalone application cases.
In the main components of the application, we will code its behavior as follows:
@Component({
selector: ‘app-root’,
standalone: true,
imports: [CommonModule, ReactiveFormsModule],
templateUrl: ‘./app.component.html’,
styleUrls: [‘./app.component.css’],
})
export class AppComponent {
private formBuilder = inject(NonNullableFormBuilder);
private exerciseService = inject(ExercisesService);
exerciseList$ = this.exerciseService.getExercises();
public entryForm = this.formBuilder.group({
description: [”, Validators.required],
});
newExercise() {
if (this.entryForm.valid) {
const newExercise = { …this.entryForm.value };
this.exerciseService
.addExercises(newExercise)
.subscribe(
(_) => (this.exerciseList$ = this.exerciseService.getExercises())
);
}
}
}
Let’s first highlight the component configuration in the @Component decorator metadata. The standalone property means that this component can be used directly without being declared in any module. In the imports property, we declare its dependencies, which are CommonModule, the basis for any Angular component, and ReactiveFormsModule, as we will be developing a reactive form (for more details about the form, read Chapter 6, Handling User Input: Forms). In the component, we are injecting NonNullableFormBuilder and ExercisesService and we take the initial list and assign it to the exerciseList$ attribute. We create the form object with the formBuilder service, and finally, we create the newExercise method responsible for the Submit button.
As we will have the list of exercises in the same form, in the subscribe method, we assign the exerciseList$ attribute again to refresh the list.
To finish the component, let’s create its template as follows:
<div class=”bg-gray-100 flex justify-center items-center min-h-screen”>
<div class=”max-w-md w-full p-6 bg-white rounded-lg shadow-md”>
<h1 class=”text-2xl font-bold mb-4″>Exercise List</h1>
<div class=”max-h-40 overflow-y-auto mb-4″>
<ul>
<li class=”mb-2″ *ngFor=”let exercise of exerciseList$ | async”>
{{ exercise.description }}
</li>
</ul>
</div>
</div>
</div>
In the first part, we have the list of exercises, and here we are using Angular’s async pipe to subscribe and search the list (for more details, read Chapter 9, Exploring Reactivity with RxJS).
In the same template file, we will add the form:
<h2 class=”text-xl font-semibold mt-6 mb-2″>Add Exercise</h2>
<form [formGroup]=”entryForm” (ngSubmit)=”newExercise()” class=”space-y-2″>
<div class=”mb-4″>
<label for=”description” class=”mb-2 block font-bold text-gray-700″>Description:</label>
<input type=”text” id=”description” name=”description” class=”w-full appearance-none rounded border px-3 py-2 leading-tight text-gray-700 shadow” formControlName=”description”/>
<div *ngIf=”entryForm.get(‘exercise’)?.invalid && entryForm.get(‘exercise’)?.touched” class=”mt-1 text-red-500″>
Exercise is required.
</div>
</div>
<div class=”flex items-center justify-center”>
<button type=”submit” [disabled]=”entryForm.invalid” [class.opacity-50]=”entryForm.invalid” class=”rounded bg-blue-500 px-4 py-2 font-bold text-white hover:bg-blue-700″ >
Confirm
</button>
</div>
</form>
We created a reactive form with just the Description field and added simple validation.
By running our application with the ng serve command, we will have the following interface:

Figure 11.2 – Exercise form
With our micro frontend project ready, we can prepare it to be consumed by our main application.
No Responses