Casey Harrils
Casey Harrils

Reputation: 2963

Angular Material 8 formControlName error - getting conflicting messages

I am attempting to work with Angular Material (8) Reactive Forms. I am working on a Registration Form. I am getting errors that seem to contradict each other.

**

When I do it this way (file: register.component.html):

**

  <!-- Form -->
            <form [formGroup]="registerForm" class="text-center" style="color: #757575;">

                <div class="form-col">
                    <div class="col">
                        <!-- First name -->
                        <div class="md-form">
                            <input required type="text" id="materialRegisterFormFirstName" class="form-control" 
                            mdbInput   [(ngModel)]="user.firstname"/>
                            <label for="materialRegisterFormFirstName">First name</label>
                        </div>
                    </div>

[... snip ...]

**

I get this error:

**

ERROR Error: 
      ngModel cannot be used to register form controls with a parent formGroup directive.  Try using
      formGroup's partner directive "formControlName" instead.  

enter image description here

So, I follow the instructions. When I use this approach (adding in formControlName="firstname"),

            <div class="form-col">
                <div class="col">
                    <!-- First name -->
                    <div class="md-form">
                        <input required type="text" id="materialRegisterFormFirstName" class="form-control" 
                        mdbInput formControlName="firstname"  [(ngModel)]="user.firstname"/>
                        <label for="materialRegisterFormFirstName">First name</label>
                    </div>
                </div>

[... snip ...]

**

I get the following error:

**

forms.js:2312 
    It looks like you're using ngModel on the same form field as formControlName. 
    Support for using the ngModel input property and ngModelChange event with 
    reactive form directives has been deprecated in Angular v6 and will be removed 
    in Angular v7.

    For more information on this, see our API docs here:
    https://angular.io/api/forms/FormControlName#use-with-ngmodel

When looking up the problem, I come across this in an old thread:

REFERENCE: ngModel on the same form field as formControlName

From Angular 7 and onward you can't use both formControlName and ngModel together. If you want to use template-driven forms you can go with ngModel and if you want to use reactive forms you can't go with ngModel. (Simple)

**

It sounds like it is saying to remove the formControlName reference. How can this problem be resolved?

**

TIA

Upvotes: 0

Views: 1912

Answers (4)

Raviteja V
Raviteja V

Reputation: 344

You Cannot use both ngModel and FormControlName or ngModel and formGroup together. Because ngModel is a template forms driven whereas FormControlName and FormGroup are reactive forms driven.

If you want to use both together you are increasing the complexity of the application. If you want to access the value through formControlName then use it like

    <form [formGroup]="registerForm" class="text-center" style="color: #757575;">
      <div class="form-col">
       <div class="col">
        <div class="md-form">
         <input formControlName="firstName" type="text" id="materialRegisterFormFirstName" class="form-control" mdbInput/>
          <label for="materialRegisterFormFirstName">First name</label>
        </div>
       </div>
     </div>
   </form>

In component.ts file write like

registerForm = new FormGroup({
    firstName: new FormControl([Validator.required]),
});

or else you can build formgroup using formbuilder, fb is an instance of formBuilder

this.registerForm = fb.group({
    'fullname': ['', Validators.required],
});

and you can read value like this

this.user.firstName = this.registerForm.get('firstName').value;

Upvotes: 2

Savan Padaliya
Savan Padaliya

Reputation: 872

That is because you are using template-driven and reactive form at the same time. You need to use it one of them, you cant use both at same time.

Syntax of template driven form is as below.

.html file

<div class="row">
  <div class="col-xs-12">
    <form (ngSubmit)="onSubmit()">
      <div class="row">
        <div class="col-sm-5 form-group">
          <label for="courseName">Course Name</label>
          <input
            type="text"
            id="courseName"
            class="form-control"
            name="courseName"
            ngModel>
        </div>
        <div class="col-sm-2 form-group">
          <label for="courseDesc">Course Description</label>
          <input
            type="text"
            id="courseDesc"
            class="form-control"
            name="courseDesc"
            ngModel>
        </div>
        <div class="col-sm-2 form-group">
          <label for="courseAmount">Course Amount</label>
          <input
            type="number"
            id="courseAmount"
            class="form-control"
            name="courseAmount"
            ngModel>
        </div>
      </div>
      <div class="row">
        <div class="col-xs-12">
          <button
            class="btn btn-success"
            type="submit">Add</button>
          <button
            class="btn btn-danger"
            type="button">Delete</button>
          <button class="btn btn-primary" type="button">Clear</button>
        </div>
      </div>
    </form>
  </div>
</div>

.ts file

onSubmit(form: NgForm) {
    console.log("Course Name is : " + form.value.courseName);
    console.log("Course Desc is : " + form.value.courseDesc);
    console.log("Course Amount is : " + form.value.courseAmount);    
  }

Syntax for Reactive Form as below

.html file.

<div class="row">
  <div class="col-xs-12">
    <form [formGroup]="courseForm" (ngSubmit)="onSubmit()">
      <div class="row">
        <div class="col-sm-5 form-group">
          <label for="courseName">Course Name</label>
          <input
            type="text"
            id="courseName"
            class="form-control"
            formControlName="courseName">
        </div>
        <div class="col-sm-2 form-group">
          <label for="courseDesc">Course Description</label>
          <input
            type="text"
            id="courseDesc"
            class="form-control"
            formControlName="courseDesc">
        </div>
        <div class="col-sm-2 form-group">
          <label for="courseAmount">Course Amount</label>
          <input
            type="number"
            id="courseAmount"
            class="form-control"
            formControlName="courseAmount">
        </div>
      </div>
      <div class="row">
        <div class="col-xs-12">
          <button
            class="btn btn-success"
            type="submit">Add</button>
          <button
            class="btn btn-danger"
            type="button">Delete</button>
          <button class="btn btn-primary" type="button">Clear</button>
        </div>
      </div>
    </form>
  </div>
</div>

.ts file

this.courseForm = new FormGroup({
          'courseName': new FormControl(null, Validators.required),
          'courseDesc': new FormControl([Validators.required, Validators.minLength(100)]),
          'courseAmount': new FormControl(null)
        });

for more reference visit

Upvotes: 3

Edison Augusthy
Edison Augusthy

Reputation: 1573

since you are using reactive forms , no need to use ngModelin your input fields use formControlName insted. ngModel is used in template driven froms

<div class="md-form">
  <input required type="text" id="materialRegisterFormFirstName" class="form-control" 
   mdbInput formControlName="firstname"/>
  <label for="materialRegisterFormFirstName">First name</label>
</div>

here you can find better examples https://v8.angular.io/guide/reactive-forms

Upvotes: 0

Sachila Ranawaka
Sachila Ranawaka

Reputation: 41387

Use [ngModelOptions]="{ standalone: true }" on the input element

Upvotes: 0

Related Questions