angulartypescriptmodelangular-reactive-formsformgroups

Model is incompatible with FormGroup


I'm new in Angular, I made an API POST with a model, but that model isn't compatible with my FormGroup, and I don't understand how to set up the FormGroup. I guess, I have to put something so that the variables are not null or undefined.

My FormGroup:

NormaForm = new FormGroup({
  codSector: new FormControl<number>(0, [Validators.required]),
  numNorma: new FormControl<number>(0, [Validators.required]),
  denominacion: new FormControl('', [Validators.required]),
  sumilla: new FormControl('', [Validators.required]),
  contenido: new FormControl('', [Validators.required]),
  tipoNormaId: new FormControl<number>(0, [Validators.required]),
  fechaPublicacion: new FormControl('', [Validators.required]),
})

get codSector() { return this.NormaForm.get('codSector'); }
get numNorma() { return this.NormaForm.get('numNorma'); }
get denominacion() { return this.NormaForm.get('denominacion'); }
get sumilla() { return this.NormaForm.get('sumilla'); } 
get contenido() { return this.NormaForm.get('contenido'); } 
get tipoNormaId() { return this.NormaForm.get('tipoNormaId'); } 
get fechaPublicacion() { return this.NormaForm.get('fechaPublicacion'); } 

My form (is somewhat long, so I'll just put the beginning):

<form [formGroup]="NormaForm" (ngSubmit)="onSubmit_crear_norma(this.NormaForm.value)">
  <div class="px-1 py-1 mb-3 wrap-horizontal-filter">
    <div  class="pb-1" fxLayout fxLayout.lt-md="column" fxLayoutGap="10px">

      <div fxFlex fxLayout="column" fxLayoutGap="10px">
        <div fxFlex="50%" fxLayout="row" fxLayout.lt-sm="column" fxLayoutAlign="center center" fxLayoutAlign.lt-sm="stretch" fxLayoutGap="10px">
          <label fxFlex="30%">Código de sector:</label>
          <input fxFlex type="number" class="form-control mb-2" formControlName="codSector"/>
        </div>

My model:

export interface NormaPost {
  "codSector": number,          
  "numNorma": number,             
  "denominacion": string,  
  "sumilla": string,        
  "contenido": string,       
  "tipoNormaId": number,          
  "fechaPublicacion": Date
}

The API function:

onSubmit_crear_norma(normaPost:NormaPost): void {
      
  this.normaService.postNorma(normaPost).subscribe(resp=>{
    this.nueva_norma = resp;
    console.log(this.nueva_norma)
  }, err => {
    this.toastr.error("Error desconocido");
  });
}

Image error in Visual Studio Code:

Argument of type 'Partial<{ codSector: number | null; numNorma: number | null; denominacion: string | null; sumilla: string | null; contenido: string | null; tipoNormaId: number | null; fechaPublicacion: string | null; }>' is not assignable to parameter of type 'NormaPost'. Types of property '"codSector"' are incompatible. Type 'number | null | undefined' is not assignable to type 'number'. Type 'undefined' is not assignable to type 'number'.ngtsc(2345) modal-norma-creacion.component.ts(11, 60): Error occurs in the template of component ModalNormaCreacionComponent.


Solution

  • As start from Angular 14 which introduces the strict form types,

    If you want to implement all the form controls in the Form Group as non-nullable:

    1. Get the NonullableFormBuilder service from the dependency injection.

    2. Create NormaForm form group instance with NonullableFormBuilder service.

    constructor(private fb: NonNullableFormBuilder) {}
    
    NormaForm! = FormGroup;
    
    ngOnInit() {
      this.NormaForm = this.fb.group({
        codSector: [0, { validators: [Validators.required] }],
        numNorma: [0, [Validators.required]],
        denominacion: ['', [Validators.required]],
        sumilla: ['', [Validators.required]],
        contenido: ['', [Validators.required]],
        tipoNormaId: [0, [Validators.required]],
        fechaPublicacion: [new Date(), [Validators.required]],
      });
    }
    
    1. Well, you don't need to pass the NormaForm.value from the view as you can get it in the component.
    <form [formGroup]="NormaForm" (ngSubmit)="onSubmit_crear_norma()">
    
      ...
    
    </form>
    
    1. In the onSubmit_crear_norma method, get the this.NormaForm.value and cast it as NormaPost type.
    onSubmit_crear_norma(): void {
          
        this.normaService.postNorma(this.NormaForm.value as NormaPost).subscribe(resp=>{
          this.nueva_norma = resp;
          console.log(this.nueva_norma)
        }, err => {
          this.toastr.error("Error desconocido");
      });
    }
    

    Demo @ StackBlitz