0
votes

I'm using the official published documentation sample code at https://angular.io/api/forms/NgModelGroup

though I find I still have the issue WITHOUT USING the ngModelGroup directive

form.component.ts

import {Component} from '@angular/core';
import {NgForm} from '@angular/forms';

@Component({
 selector: 'example-app',

template: `
<form #f="ngForm" (ngSubmit)="onSubmit(f)">
  <p *ngIf="nameCtrl.invalid">Name is invalid.</p>

  <div ngModelGroup="name" #nameCtrl="ngModelGroup">
    <input name="first" [ngModel]="name.first" minlength="2">
    <input name="last" [ngModel]="name.last" required>
  </div>

  <input name="email" ngModel> 
  <button>Submit</button>
</form>

<button (click)="setValue()">Set value</button>
`,
})
export class FormComponent {
name = {first: 'Nancy', last: 'Drew'};

onSubmit(f: NgForm) {
console.log(f.value);  // {name: {first: 'Nancy', last: 'Drew'}, email: ''}
console.log(f.valid);  // true
}

setValue() { this.name = {first: 'Bess', last: 'Marvin'}; }
}

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { NgForm, NgModelGroup, NgModel } from '@angular/forms';
import { AppComponent } from './app.component';
import { FormComponent } from './form/form.component';


@NgModule({
declarations: [
AppComponent,
FormComponent,
NgForm,NgModelGroup,NgModel

],
imports: [
BrowserModule,
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }

app.component.html <example-app></example-app>

and in Console receiving this error: Uncaught (in promise): Error:

ERROR Error: Uncaught (in promise): Error: No value accessor for form control with path: 'name -> first' Error: No value accessor for form control with path: 'name -> first' at _throwError (forms.es5.js:1918) at setUpControl (forms.es5.js:1828) at forms.es5.js:3955 at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:392) at Object.onInvoke (core.es5.js:3890) at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:391) at Zone.webpackJsonp.../../../../zone.js/dist/zone.js.Zone.run (zone.js:142) at zone.js:844 at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:425) at Object.onInvokeTask (core.es5.js:3881) at _throwError (forms.es5.js:1918) at setUpControl (forms.es5.js:1828) at forms.es5.js:3955 at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:392) at Object.onInvoke (core.es5.js:3890) at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:391) at Zone.webpackJsonp.../../../../zone.js/dist/zone.js.Zone.run (zone.js:142) at zone.js:844 at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:425) at Object.onInvokeTask (core.es5.js:3881) at resolvePromise (zone.js:795) at zone.js:847 at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:425) at Object.onInvokeTask (core.es5.js:3881) at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:424) at Zone.webpackJsonp.../../../../zone.js/dist/zone.js.Zone.runTask (zone.js:192) at drainMicroTaskQueue (zone.js:602) at

@angular/cli: 1.3.2

node: 6.11.0

os: win32 x64

@angular/animations: 4.3.6

@angular/common: 4.3.6

@angular/compiler: 4.3.6

@angular/core: 4.3.6

@angular/forms: 4.3.6

@angular/http: 4.3.6

@angular/platform-browser: 4.3.6

@angular/platform-browser-dynamic: 4.3.6

@angular/router: 4.3.6

@angular/cli: 1.3.2

@angular/compiler-cli: 4.3.6

@angular/language-service: 4.3.6

2
I just copied the code from the referenced documentation and pasted it into a Plunker and it seems to work fine. The plunker is here: plnkr.co/edit/ZnjOGq9U1vZmX3XndHQI?p=preview Is it possible the error is somewhere else in the code? Do you have the ngModule updated for this component and for the FormsModule? - DeborahK
@DeborahK I've updated the question with all relevant files. The HTML you put in plunker is totally different than what my compiler is producing. Your HTML has no Javascript bundles. -thx - arod
I don't understand? I am just using Plunker's standard Angular template and then pasting in the code from the docs as you said you used? - DeborahK

2 Answers

1
votes

If you're going to use NgForm, NgModel and other such stuff in your custom component then you'll need to import FormsModule into the NgModule which declares your component. BTW, your link provides module name (FormsModule) which you need to import. Also, you don't need to declare directives NgForm, NgModelGroup and NgModel separately since they're already declared in the FormsModule.

So, your module should look something like this:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { FormComponent } from './form/form.component';

@NgModule({
    declarations: [
        AppComponent,
        FormComponent
    ],
    imports: [
        BrowserModule,
        FormsModule // <-- this is what you need to do
    ],
    providers: [],
    bootstrap: [AppComponent]
})
export class AppModule { }

Explanation of this exact error

In fact, the error is pretty much self-explanatory. You need to provide something that implements ControlValueAccessor interface (DefaultValueAccessor would be used in your particular case), because NgModel which you put on the input requires it. Class that implements ControlValueAccessor is what actually puts value in the DOM element and handles user input from it. This is an angular's abstraction of DOM user input elements of different types - radio buttons, checkboxes, text inputs, and selects, to name a few. So, since you have not given anything that implements this interface (and provides said implementation using NG_VALUE_ACCESSOR token), angular injector complains that it cannot instantiate NgModel for this reason. But if you import FormsModule then you will get all this stuff at once since this module provides several value accessors out of the box with no additional declarations.

0
votes

Adding FormsModule to the imports array in app.module.ts solved this:

imports: [
    BrowserModule,
    FormsModule // <-- this is what you need to do
],