Angular FormControl objects are able to accept input values of any type, or are restricted to typescript primitive types?

Viewed 5593

I am using FormControl objects in a FormGroup to create a reactive form in Angular. There is no problem when I pass primitive arguments as a value of an HTML input select control. However, when I pass an object of a self-defined class, the value in the FormControl is reduced to [object Object].

The system I am working in includes: Angular CLI: 7.1.4; Node: 10.15.0; Angular: 7.1.4; rxjs 6.3.3; typescript 3.1.6; webpack 4.23.1; Linux rdz1 4.15.0-43-generic #46-Ubuntu SMP Thu Dec 6 14:45:28 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';

@Component({
    selector: 'app-header-notes',
    templateUrl: './header-notes.component.html',
    styleUrls: ['./header-notes.component.css']
})

export class HeaderNotesComponent implements OnInit {
    ndcForm = new FormGroup({
        noteType: new FormControl(''),
        noteDate: new FormControl(''),
        noteFor: new FormControl(''),
        noteTo: new FormControl(''),
        noteDetail: new FormControl(''),
        noteDetailVal: new FormControl(''),
        noteChkRefInvoice: new FormControl('')
    });

    ngOnInit() { this.onChanges(); }

    onChanges(): void{
        this.ndcForm.valueChanges
        .subscribe( val => console.log(val))
    }
}

The console shows something like: {noteType: "credit", noteDate: "2019-01-01", noteTo: [object Object], ... }

I am passing an object {param1: val1, parm2: val2} to "noteTo" , so I would expect to watch this value in the console, however it is showing [object Object]. It looks like if the object has been stringified.

2 Answers

I have found the answer. In the form, instead of using:

<option *ngFor="let cargoAg of dfCargoAgs" [value]="cargoAg">{{cargoAg.nombre}}</option>

I had to use:

<option *ngFor="let cargoAg of dfCargoAgs" [ngValue]="cargoAg">{{cargoAg.nombre}}</option>

So [value] accepts only primitive types, but [ngValue] can accept objects of any class. I hope this can be helpful.

You are correct in assuming that the object is being "stringified".

You can override toString() on your custom type in order to get the desired output in the form in HTML.

However, if you want to be able to convert back from the form to get the value as an object of that custom type then you will have to create a method for doing so, which can be kind of annoying.

Another solution would be to break out the properties of your custom type into a nested FormGroup inside of your ndcForm FormGroup, like so:

ndcForm: FormGroup = new FormGroup({
    noteType: new FormControl(''),
    noteDate: new FormControl(''),
    noteFor: new FormControl(''),
    noteTo: new FormGroup({
        any: new FormControl(''),
        custom: new FormControl(''),
        property: new FormControl('')
    }),
    noteDetail: new FormControl(''),
    noteDetailVal: new FormControl(''),
    noteChkRefInvoice: new FormControl('')
});

You will have to take some care to extract each value from the object to place it into the form, and vice versa.

Go to the Angular docs for info on nesting FormGroup instances.

Related