Error in mat-select when trying to choose an item

Asked

Viewed 352 times

0

Error:

ngModel cannot be used to Register form Controls with a Parent formGroup Directive. Try using formGroup’s Partner Directive "formControlName" Instead. Example:

My HTML

<div class="container">
    <form [formGroup]="createForm" (ngSubmit)="postCreateFields()" style="width:400px; margin: 0 auto;">
      <h1>Create Fields</h1>

      <div class="required-field-block">
          <input formControlName="name" type="text" placeholder="Nome" class="form-control">
          <div class="required-icon">
              <div class="text">*</div>
          </div>
      </div>

      <div class="required-field-block">
          <input formControlName="typeField" type="text" placeholder="Field" class="form-control">
          <div class="required-icon">
              <div class="text">*</div>
          </div>
      </div>

      <div>
    <mat-form-field>
      <mat-select formControlName="typeField" placeholder="Type Fields" [(ngModel)]="dataSource" name="field">
        <mat-option  *ngFor="let field of dataSource" [value]="field.name">   
          {{field.name}}
        </mat-option>
      </mat-select>
    </mat-form-field>
  </div>

      <button type="submit" class="btn btn-primary" >Criar</button>
  </form>
  </div>

My Component

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '../../../node_modules/@angular/forms';
import { CreateFieldsService } from '../Services/Fields/create-fields.service';

@Component({
  selector: 'app-create-fields',
  templateUrl: './create-fields.component.html',
  styleUrls: ['./create-fields.component.css'],
  providers: [CreateFieldsService]
})
export class CreateFieldsComponent implements OnInit {

  createForm :FormGroup;
  private _createFields: Model.CreateFields;

  selectedValue: string;
  private operUrl: 'api/TypesFields';
  public dataSource: Model.Itens[];

  constructor(private _createFieldService: CreateFieldsService, private builder: FormBuilder) { 
    this.createForm = this.builder.group({
     name: ''
   }) 
 } 

  ngOnInit() {

    this._createFieldService
    .getAll<Model.Result>()
    .subscribe((data: Model.Result) => {
      debugger;
      this.dataSource = data.itens;
    });

  }
  onPostCreateFields(){
    this._createFields = this.createForm.value;
    this._createFieldService.postCreateFields(this._createFields)
        .subscribe( success => {
          if(success.Result){
          }
        },
        error =>{
        }
      );
    }
}

How do I fix this error? The error in the browser points to line 13 of the html, referring to this: <input formControlName="typeField" type="text" placeholder="Field" class="form-control">

EDIT1

Actually the problem is in my mat-select, in this html line

<div>
    <mat-form-field>
      <mat-select formControlName="typeField" placeholder="Type Fields" [(ngModel)]="dataSource" name="field">
        <mat-option  *ngFor="let field of dataSource" [value]="field.name">   
          {{field.name}}
        </mat-option>
      </mat-select>
    </mat-form-field>
  </div>

EDIT2

I changed it to this and no longer gave the error

<div>
        <mat-form-field>
          <mat-select formControlName="typeField" placeholder="Type Fields" [(ngModel)]="typeField" name="field">
            <mat-option  *ngFor="let field of dataSource" [value]="field.name">   
              {{field.name}}
            </mat-option>
          </mat-select>
        </mat-form-field>
      </div>

EDIT3

so became my compoent

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '../../../node_modules/@angular/forms';
import { CreateFieldsService } from '../Services/Fields/create-fields.service';

@Component({
  selector: 'app-create-fields',
  templateUrl: './create-fields.component.html',
  styleUrls: ['./create-fields.component.css'],
  providers: [CreateFieldsService]
})
export class CreateFieldsComponent implements OnInit {

  createForm :FormGroup;
  private _createFields: Model.CreateFields;

  selectedValue: string;
  private operUrl: 'api/Fields';
  public dataSource: Model.CreateTypeFieldItem[];

  constructor(private _createFieldService: CreateFieldsService, private builder: FormBuilder) { 
    this.createForm = this.builder.group({
     name: '',
     typeField:  ''

   });
 } 

  ngOnInit() {

    this._createFieldService
    .getAll<Model.Result<Model.CreateTypeFieldItem>>()
    .subscribe((data: Model.Result<Model.CreateTypeFieldItem>) => {
      debugger;
      this.dataSource = data.itens;
    });    
  }

  onPostCreateFields(){
    let formValue = this.createForm.value;
    this._createFields ={
      name: formValue.name,
      typeField: {
        typeFieldId: <string>formValue.typeField
      }
    };

    this._createFieldService.postCreateFields(this._createFields)
        .subscribe( success => {
          if(success.Result){
        }
      },
        error =>{
      }
    );
  }
}
  • 1

    you cannot use the attribute name. You have to use formControlName. It is well described here: fix(Forms): improve ngModel error messages

  • @Williamjohnadamtrindade, I use formControlName now. Check out my post

  • Improve the title of your question. And no.. is not: <mat-select placeholder="Type Fields" [(ngModel)]="dataSource" name="field">

  • You’re right. I edited it and put it there and it keeps going wrong: Error trying to diff '_string'. Only arrays and iterables are allowed. The _string is the field value within the dropdown that I want to persist with.

1 answer

1

I tidied up your code and added comments on the changes I made or you need to make.

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms'; //arrumar import
import { CreateFieldsService } from '../Services/Fields/create-fields.service'; //not needed

@Component({
  selector: 'app-create-fields',
  templateUrl: './create-fields.component.html',
  styleUrls: ['./create-fields.component.css'],
  providers: [CreateFieldsService] // usa o providers do module, ou se for o angular 6 vc pode usar o provideIn: 'root' no proprio servico
})
export class CreateFieldsComponent implements OnInit {

  createForm :FormGroup;
  private _createFields: Model.CreateFields;

  selectedValue: string;
  private operUrl: 'api/TypesFields';
  dataSource: Model.Itens[];  // evite propriedade privadas ja que elas nao podem ser usadas no template.

  constructor(private _createFieldService: CreateFieldsService, private builder: FormBuilder) { 
//constructor sempre vazio, codigo de inicializacao ngOnInit
 } 

  ngOnInit() {
 //vc precisa de um control pra cada user input seja um select ou o que for.
this.createForm = this.builder.group({
     name: '', // -->seu input
     typeField: '' // -->seu select
   }) 

    this._createFieldService
    .getAll<Model.Result>()
    .subscribe((data: Model.Result) => {
      debugger;
      this.dataSource = data.itens;
    });

  }
  onPostCreateFields(){
    this._createFields = this.createForm.value;
    this._createFieldService.postCreateFields(this._createFields)
        .subscribe( success => {
          if(success.Result){
          }
        },
        error =>{
        }
      );
    }
}

Html --> remove all ngModel. Either vc uses the Forms template or reactiveForms

<mat-select formControlName="typeField" placeholder="Type Fields" name="field">
    <mat-option  *ngFor="let field of dataSource" [value]="field.name">   
      {{field.name}}
    </mat-option>
  </mat-select>
</mat-form-field>
  • Actually there are more things. I managed to fix it. O Model.Result I had to change and called her in my method. See Edit3

  • see the other changes I’ve made. You don’t need to put public in front of the properties. What’s wrong now?

  • No, it’s wrong. I managed to fix it with the code posted and your tip is correct. Only the Model.Result is giving a blow, I had to make the changes above in EDIT3.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.