Posting a form with multiple images in Angular

Hello everybody,

I’m developing a website in which you can fill in a form with multiple images. I also programmed the backend and it works well (tested with Postman), also when served because I can see the results in the frontend.

I am using node, express and MongoDB in the backend, and I combine it with multer for image uploads. The code for the backend can be found at this github repo.

In the frontend (available in this github repo) I’m using Angular 9. But I can’t get the form in new-project to be sent properly to the backend.

This is the form

...
private createForm(): void {
    this._projectForm = this.fb.group({
      title: ['', [Validators.required]],
      description: ['', [Validators.required]],
      mainImage: [null, [Validators.required]],
      texts: this.fb.array([this.createText('')]),
      images: this.fb.array([this.createImage()])
    });

    this._texts = this.texts;
    this._images = this.images;
  }
...

Which is then populated with the values from the bound elements in the html:

<form [formGroup]="projectForm" novalidate="novalidate" class="px-5 container">
    <!-- Project title -->
    <div class="row form-group">
      <label class="mb-0 w-25 text-right">
        <h4 class="mb-0 pr-2">Title:</h4>
      </label>
      <input type="text" class="form-control w-75" placeholder="Project title" formControlName="title" />
    </div>
    <!-- Project description -->
    <div class="row form-group">
      <label class="mb-0 w-25 text-right">
        <h4 class="mb-0 pr-2">Description:</h4>
      </label>
      <input type="text" class="form-control w-75" placeholder="Project description" formControlName="description" />
    </div>
    <!-- Main image -->
    <div class="row form-group">
      <label class="mb-0 w-25 text-right">
        <h4 class="mb-0 pr-2">Main image:</h4>
      </label>
      <input type="file" class="form-control-file w-75" accept="image/*" data-formcontrolname="mainImage"
        formControlName="mainImage" (change)="onFileSelected($event)">
    </div>
    <!-- Texts and images -->
    <div class="row form-group">
      <!-- Texts -->
      <div formArrayName="texts" class="col">
        <h2 class="text-center">Texts</h2>
        <div *ngFor="let control of texts.controls; let i = index">
          <div [formGroupName]="i" class="row form-group">
            <div class="col-2 d-flex justify-content-end align-items-center">
              <label class="mb-0">
                <h4 class="mb-0">{{i+1}}:</h4>
              </label>
            </div>
            <div class="col-9 d-flex justify-content-center align-items-center">
              <input type="text" class="form-control w-100" placeholder="Lorem ipsum..." formControlName="text">
            </div>
            <div class="col-1 d-flex align-items-center">
              <button class="btn btn-danger" (click)="deleteText(i)">&times;</button>
            </div>
          </div>
        </div>
        <div class="row">
          <div class="col-2"></div>
          <div class="col-9">
            <button class="btn btn-success w-100" (click)="addText()">add</button>
          </div>
          <div class="col-1"></div>
        </div>
      </div>
      <!-- Images -->
      <div formArrayName="images" class="col">
        <h2 class="text-center">Images</h2>
        <div *ngFor="let control of images.controls; let i = index">
          <div [formGroupName]="i" class="row form-group">
            <div class="col-2 d-flex justify-content-end align-items-center">
              <label class="mb-0">
                <h4 class="mb-0">{{i+1}}:</h4>
              </label>
            </div>
            <div class="col-9 d-flex justify-content-center align-items-center">
              <input type="file" class="form-control-file" accept="image/*" data-formcontrolname="image"
                formControlName="image" (change)="onFileSelected($event)">
            </div>
            <div class="col-1 d-flex align-items-center">
              <button class="btn btn-danger" (click)="deleteImage(i)">&times;</button>
            </div>
          </div>
        </div>
        <div class="row">
          <div class="col-2"></div>
          <div class="col-9">
            <button class="btn btn-success w-100" (click)="addImage()">add</button>
          </div>
          <div class="col-1"></div>
        </div>
      </div>
    </div>
    <div class="d-flex justify-content-center mt-3">
      <button [disabled]="disabled" class="btn btn-primary" (click)="submit()">{{submitText}}</button>
    </div>
  </form>

Then, on submit:

public submit(): void {
    this.projectService.postNewProject(this.projectForm).subscribe((res) => {
      console.log(res);
    });
  }

I created a service called ProjectService which should be the one responsible for contacting the backend and serving the data to the frontend. The called method is the following:

public postNewProject(form: FormGroup) {
    let body = new HttpParams();
    for (const formField in form.value) {
      body = body.set(formField, form.value[formField]);
    }
    const headers = new HttpHeaders({
      'Content-Type': 'application/x-www-form-urlencoded'
    });
    return this.http.post(this.postNewProjectUrl, body, {
      headers,
      observe: 'response'
    });
  }

I have tried several things already but none worked.

Thanks in advance to everybody!