Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mapping FormGroup to Interface Object

I've been attempting to bind form data in my angular HTML template to an interface in my Component.

I've been following the below tutorial, but my FormGroup is not auto-casting to the interface on the back-end as the tutorial does.

  • Reactive Forms Tutorial

My code is as follows:


Component

import { Component, OnInit } from "@angular/core";
import { FormGroup, FormBuilder, FormArray, FormControl, Validators } from "@angular/forms";
import { DeckBuildRequest } from "../domain-models/interfaces/deckBuildRequest.interface";

@Component({
  selector: "deck-options",
  templateUrl: "./deck-options.component.html",
  styleUrls: ["./deck-options.component.css"]
})
export class DeckOptionsComponent {
  private deckBuildRequest: FormGroup;

  constructor(formBuilder: FormBuilder) {
    this.deckBuildRequest = formBuilder.group({
      "deckSize": 60,
      "deckColors": formBuilder.array([
          {color: "Blue", checked: false},
          {color: "Green", checked: false},
          {color: "Red", checked: false},
          {color: "White", checked: false},
          {color: "Black", checked: false},
          {color: "Colorless", checked: false}
        ])
    });
  }

  GenerateDeck(request: DeckBuildRequest) {
    alert(request.deckSize);
  }

}

HTML

<div id="deck-options">
      <form [formGroup]="deckBuildRequest"
            (ngSubmit)="GenerateDeck(deckBuildRequest)">
        <span>
          <label><input formControlName="deckSize" type="number" max="100" min="1">Number of Cards</label>
        </span>
        <div>
          <label [attr.for]="'color'+i"
            *ngFor="let colorOption of deckBuildRequest.controls['deckColors'].controls, let i = index"
          >
            <input 
                  type="checkbox"
                  id="color{{i}}"
                  value="{{colorOption.value.color}}"
                  ng-checked="colorOption.value.checked"
            />
            {{colorOption.value.color}}
          </label>
        </div>

        <button type="submit">Generate Deck!</button>
      </form>
    </div>

Interface

export interface DeckBuildRequest {
    deckSize: number;
    deckColors: [{
        color: string;
        checked: boolean;
    }];
}

What am I missing here?

like image 686
Ivory_Tower Avatar asked Jun 22 '17 19:06

Ivory_Tower


2 Answers

FWIW, I got the implicit mappings to work. You can pass along the value of the formGroup from the View and implicitly cast to an interface on the Component side.

Simply pass along the FormGroup structure values by calling ".getRawValue()" or ".value" to the Component that expects an interface as a parameter to implicitly cast.

Html

<form (ngSubmit)="submit(Form.value)"> ... </form>

component.ts

submit(instance: ObjectClass){
 console.log(instance); // just to check if it worked 
}

There is one important distinction between ".getRawValue()" and ".value" is that getRawValue returns values from disabled controls while value only returns values from controls that are enabled.

like image 185
Ivory_Tower Avatar answered Nov 17 '22 01:11

Ivory_Tower


(ngSubmit)="GenerateDeck(deckBuildRequest.getRawValue())"

Replace this on form html. it's work for me.

like image 33
ÄR Âmmãř Żąîñh Avatar answered Nov 17 '22 02:11

ÄR Âmmãř Żąîñh