I have tried importing the FormsModule and NgForm modules as well as adding the FormsModule to the imports array.
Below is my code:
//our root app component
import { Component, NgModule, VERSION } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import {FormsModule, NgForm} from '#angular/forms';
#Component({
selector: 'my-app',
template: `
<form #searchForm="ngForm">
<input type="text" required [(ngModel)]="model.search" ngControl="search" #inputSearch="ngForm">
<p class="error" [hidden]="inputSearch.valid"> This input is required</p>
</form>
`,
styles: [`
.error {
color: red;
font-size: 11px;
}
`]
})
export class App {
public model = {
search: ""
}
constructor() {
}
}
#NgModule({
imports: [BrowserModule, FormsModule],
declarations: [App],
bootstrap: [App],
})
export class AppModule {}
And below is an error printout:
runtime.9ff156e16d788666a54a.js:16 Error: Template parse errors:
There is no directive with "exportAs" set to "ngForm" (" ]#searchForm="ngForm"> ]#inputSearch="ngForm"> This input is required "):
ng:///AppModule/App.html#2:76 Can't bind to 'ngModel' since it isn't a
known property of 'input'. (" ][(ngModel)]="model.search"
ngControl="search" #inputSearch="ngForm"> https://run.plnkr.co/rhpwnL6UIQwCFOKZ/src/main.js Loading
https://run.plnkr.co/rhpwnL6UIQwCFOKZ/src/main.js f #
runtime.9ff156e16d788666a54a.js:16
The error was caused by this line:
#inputSearch="ngForm"
This is the correct line:
#inputSearch="ngModel"
Here is the working example. When you use ngModel within the form tag you also need to provide value for the "name" attribute.
<form #searchForm="ngForm">
<input type="text" required name="search" [(ngModel)]="model.search" #inputSearch="ngModel">
<p class="error" [hidden]="inputSearch.valid"> This input is required</p>
</form>
This ng-directive error is faced when you have not imported the ng-module in your app.component.ts or your component is not imported and added into the declarations of #NgModule({})
import { FormsModule } from '#angular/forms';
[...]
#NgModule({
imports: [
[...]
FormsModule
],
[...]
})
Related
I have imported FormsModule in app.module.ts file.
can anyone tell me where i did mistake ?
Error
app.module.ts
import { FormsModule } from '#angular/forms';
....
imports: [
....
FormsModule,
....
]
about.component.html
<form>
<div class="form-group">
<label for="banner">Banner Image Url</label>
<input type="text"
class="form-control"
[(ngModel)]="banner.banner_image"
id="banner"
name="banner"
/>
</div>
</form>
about.component.ts
import { Component, OnInit } from '#angular/core';
import { ActivatedRoute, Router } from '#angular/router';
import {UserService} from '../../service/user.service';
class Banner {
id: number;
banner_image: number;
}
#Component({
selector: 'app-about',
templateUrl: './about.component.html',
styleUrls: ['./about.component.css']
})
export class AboutComponent implements OnInit {
banner: Banner = new Banner();
constructor() {
}
ngOnInit(): void {
}
}
I’ve had problems like this where the build doesn’t pick up a new import. Maybe try re compiling?
Import ReactiveFormsModule in app.module.ts
If this About component is a part of some nested module, then include FormsModule in nested module file.
Including it in app.module.ts will not work.
I'm following Angular tutorial on forms here:
https://angular.io/guide/reactive-forms
I have this code in 'datasources.component.html':
<form [formGroup]="queryForm">
<label>Query:
<input type="text" formControlName="query">
</label>
And this in 'datasources.component.ts':
import { Component } from '#angular/core';
import { FormGroup, FormControl } from '#angular/forms';
#Component({
selector: 'sql-editor',
templateUrl: './datasources.component.html',
styleUrls: ['./datasources.component.scss']
})
export class DatasourcesComponent {
queryForm = new FormGroup({
query: new FormControl(''),
});
}
I see its stuck at 'websocket : pending'
Also, my original intent is to make it work for 'textarea'. Is the solution going to work for that too?
<textarea class="form-control" rows="5" id="sql-query" [formControl]="query"></textarea>-
I'm using Angular version 7.2:
EDIT:
I see this error in console 'Can't bind to 'formGroup' since it isn't a known property of 'form'
Import ReactiveFormsModule in your AppModule
import { ReactiveFormsModule } from '#angular/forms';
#NgModule({
imports: [
// other imports ...
ReactiveFormsModule
],
})
export class AppModule { }
formGroup, formControl, etc are all directives that are exposed as a part of the ReactiveFormsModule.
If you want to use these directives in a Component, you'll have to either import the ReactiveFormsModule in the Module that this Component is registered in. Or you'll have to export the ReactiveFormsModule from some other module(SharedModule for instance) and then import that module in the module that you have this Component registered in.
import { ReactiveFormsModule } from '#angular/forms';
#NgModule({
imports: [
// other imports ...
ReactiveFormsModule
],
})
export class YourComponentModule { }
Also use the formcontrols like shown below:
<textarea class="form-control" rows="5" id="sql-query" formControlName="query"></textarea>
So I've been struggling with this for a long time...I've been looking into the docs, but there are so many different directives and ways to communicate between components and the DOM, but only a few good examples...
So I'm actually not even sure what I need. Let's say I have a user input in my tables.component.html file like this:
<label>Name</label>
<input id="customerName" class="form-control" required>
Then there is my tables.component.ts file which looks like this:
import { Component, OnInit } from '#angular/core';
import { isLoggedIn } from '../../assets/js/auth.js';
import { Router } from '#angular/router';
#Component({
selector: 'app-tables',
templateUrl: './tables.component.html',
styleUrls: ['./tables.component.css']
})
export class TablesComponent implements OnInit {
customers = [];
id = ""; // keep outside of object to prevent user changes
customer_form = {
name: "",
job: "",
address: "",
birthdate: "",
email: "",
}
constructor(private router: Router) { }
...
}
To make it simple: I want to bind the user input above to the customer_form.name variable in my component. I'm looking for the equivalent of Vue 2.0 models, so that if the user changes the input value, the component value changes aswell. I don't neccessarily have to push the data within a form since we've got the task not to set up any backend...
Anyway, I'm kinda confused. I read the docs, but that made it just worse. One page says I'm supposed to add a controller to the form and add a script to the bottom of the HTML, another one said I have to make a template of the form that should be stored in the component...And then there are so many different directives to bind things. I was assuming you'd want to use ngModel for that, but I couldn't seem to get that working like in the examples I found.
Thanks for any help in advance..
I have created a simple example of binding in a template-driven form: https://stackblitz.com/edit/angular-m2tkrf
Note that FormsModule is imported in app.module.ts
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { FormsModule } from '#angular/forms'; //<---- IMPORTED
import { AppComponent } from './app.component';
import { HeroFormComponent } from './hero-form/hero-form.component';
#NgModule({
imports: [
BrowserModule,
FormsModule //<---- IMPORTED IN MODULE
],
declarations: [
AppComponent,
HeroFormComponent
],
providers: [],
bootstrap: [ AppComponent ]
})
export class AppModule { }
I think what you're looking for is [(ngModel)] which is used for two-way data binding.
<input
id="customerName"
class="form-control"
required
[(ngModel)]="customer_form.name"
name="name">
PS: To use the [(ngModel)], you'll have to import FormsModule and then add it the the imports array of your AppModule or whatever module you're using it in.
...
import { FormsModule } from '#angular/forms';
...
#NgModule({
imports: [
...,
FormsModule,
...
],
...
})
export class AppModule { }
Use ngModel for two-way data binding
put [(ngModel)] on the input to pass the data from & to your property like this:
//app.module code
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { FormsModule } from '#angular/forms'; //<---- IMPORTED
import { AppComponent } from './app.component';
import { TablesComponent } from './tables.component'; //<---- IMPORTED
#NgModule({
imports: [
BrowserModule,
FormsModule //<---- IMPORTED IN MODULE
],
declarations: [
AppComponent,
TablesComponent //<---- IMPORTED
],
providers: [],
bootstrap: [ AppComponent ]
})
export class AppModule { }
//--------------------------tables.component.html
<input id="customerName" class="form-control" [(ngModel)]="customer_form.name" required>
I have just started learning. My app.components.ts file looks like this:
import { Component, NgModule } from '#angular/core';
import { FormsModule } from '#angular/forms';
#NgModule({
imports: [FormsModule ],
//...
})
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
// title = 'app';
name = '';
}
and my app.component.html is this:
<input type="text" [(ngModel)]="name">
<p>{{ name }}</p>
Javascript console is giving me following error:
compiler.es5.js:1689 Uncaught Error: Template parse errors:
Can't bind to 'ngModel' since it isn't a known property of 'input'. ("et="_blank" href="http://angularjs.blogspot.ca/">Angular blog</a></h2>
</li>
<input type="text" [ERROR ->][(ngModel)]="name">
<p>{{ name }}</p>
</ul>
"): ng:///AppModule/AppComponent.html#18:21
at syntaxError (http://localhost:4200/vendor.bundle.js:18052:34)
at TemplateParser.webpackJsonp.../../../compiler/#angular/compiler.es5.js.TemplateParser.parse (http://localhost:4200/vendor.bundle.js:29164:19)
at JitCompiler.webpackJsonp.../../../compiler/#angular/compiler.es5.js.JitCompiler._compileTemplate (http://localhost:4200/vendor.bundle.js:43209:39)
at http://localhost:4200/vendor.bundle.js:43129:62
at Set.forEach (native)
at JitCompiler.webpackJsonp.../../../compiler/#angular/compiler.es5.js.JitCompiler._compileComponents (http://localhost:4200/vendor.bundle.js:43129:19)
...
This page recommends adding FormsModule but as you can see it's not working.
Are you missing the class AppModule?
import { Component, NgModule } from '#angular/core';
import { FormsModule } from '#angular/forms';
#NgModule({
imports: [FormsModule ],
//...
})
export class AppModule {} // <-- do you have this part?
ngModel needs name into input:
<input type="text" [(ngModel)]="name" name="nome">
I'm currently using Angular Forms version 2.0.0 and trying to make a contact us modal with a contact form inside.
Immediately after the ContactComponent loads, I get:
EXCEPTION: this.form._updateTreeValidity is not a function
I've already seen some other stack posts suggesting that using FormGroup instead of FormBuilder to init the form object in the component constructor is now standard with the new API so I've updated that.
I import ReactiveFormsModule and FormsModule along with all the form related components and the error doesn't seem to be module related.
My TypeScript isn't throwing errors in compile time and Visual Studio Intellisense seems to be able to find all FormGroup functions just fine so why is this happening at runtime?...
My code:
contact.component.ts:
import { Component, Input, ViewChild } from '#angular/core';
import { ApiService } from '../../../services/api.service';
import { ModalComponent } from 'ng2-bs3-modal/ng2-bs3-modal';
import { Router, ActivatedRoute, Params } from '#angular/router';
import { FormsModule, ReactiveFormsModule, FormGroup, FormControl, Validators } from '#angular/forms';
import 'rxjs/Rx';
declare var jQuery: any;
#Component({
selector: 'my-contact',
templateUrl: 'app/modules/footer/contact/contact.html'
})
export class ContactComponent {
private contactForm: FormGroup;
private invalidEmail: boolean;
private invalidSubject: boolean;
private invalidMessage: boolean;
constructor(private apiService: ApiService, private router: Router, private route: ActivatedRoute) {
this.contactForm = new FormGroup({
emailControl: new FormControl('', <any>Validators.required),
subjectControl: new FormControl('', <any>Validators.required),
messageControl: new FormControl('', <any>Validators.required)
});
}
submit() {
if (this.contactForm.valid) {
this.apiService.sendMessage(this.contactForm.controls['emailControl'].value, this.contactForm.controls['subjectControl'].value, this.contactForm.controls['messageControl'].value);
}
if (!this.contactForm.controls['emailControl'].valid) {
this.invalidEmail = true;
}
if (!this.contactForm.controls['subjectControl'].valid) {
this.invalidSubject = true;
}
if (!this.contactForm.controls['messageControl'].valid) {
this.invalidMessage = true;
}
}
ngOnInit() {
this.invalidEmail = false;
this.invalidSubject = false;
this.invalidMessage = false;
}
}
contact.html:
<modal-header class="c-no-border" [show-close]="true">
<h4 class="modal-title text-uppercase">Send us a message</h4>
</modal-header>
<form novalidate #contactForm [formGroup]="contactForm" (ngSubmit)="submit()">
<div class="modal-body">
<div class="form-group">
<label for="email" class="control-label">Email</label>
<input name="email" formControlName="emailControl" placeholder="" type="text" class="c-square form-control c-margin-b-20" id="email">
<div class="c-font-red-1" *ngIf="invalidEmail" style="position: absolute;">*Required</div>
<label for="subject" class="control-label">Subject</label>
<input name="subject" formControlName="subjectControl" placeholder="" type="text" class="c-square form-control c-margin-b-20" id="subject">
<div class="c-font-red-1" *ngIf="invalidSubject" style="position: absolute;">*Required</div>
<textarea formControlName="messageControl" style="resize: vertical;" class="c-square form-control c-margin-b-20" id="content" (keyup.enter)="submit()"></textarea>
<div class="c-font-red-1" *ngIf="invalidMessage" style="position: absolute;">*Required</div>
</div>
</div>
<modal-footer class="c-no-padding">
<button type="button" class="btn c-btn-square c-btn-bold c-btn-uppercase pull-right">Cancel</button>
<button type="submit" class="btn c-theme-btn c-btn-square c-btn-bold c-btn-uppercase pull-right" style="margin-right: 10px;">Send</button>
</modal-footer>
</form>
app.module.ts:
import { NgModule, enableProdMode } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { AppComponent } from './app.component';
import { FormsModule, ReactiveFormsModule } from '#angular/forms';
import { Ng2Bs3ModalModule } from 'ng2-bs3-modal/ng2-bs3-modal';
import { QueuesModule } from './modules/queues/queues.module';
import { OrderModule } from './modules/order/order.module';
import { AccountModule } from './modules/account/account.module';
import { AdminModule } from './modules/admin/admin.module';
import { routing } from './app.routing';
import { GridModule } from '#progress/kendo-angular-grid';
import { SplashComponent } from './modules/splash/splash.component';
import { ContactComponent } from './modules/footer/contact/contact.component';
import { SharedModule } from './shared/shared.module';
import { EmailValidator } from './shared/utilities/custom-validators'
import { CookieService } from 'angular2-cookie/services/cookies.service';
import { HttpModule, Response } from '#angular/http';
import { StringService } from './services/string.service';
import { ApiService } from './services/api.service';
import { UserService } from './services/user.service';
import { OrderService } from './services/order.service';
import { OrderGuard } from './services/order-guard.service';
import { FooterComponent } from './modules/footer/footer.component';
import { ErrorComponent } from './modules/error/error.component';
import { CustomFormsModule } from "ng2-validation";
#NgModule({
imports: [
BrowserModule,
FormsModule,
ReactiveFormsModule,
HttpModule,
QueuesModule,
OrderModule,
AccountModule,
AdminModule,
routing,
GridModule,
SharedModule,
Ng2Bs3ModalModule,
CustomFormsModule
],
declarations: [
AppComponent,
SplashComponent,
FooterComponent,
ErrorComponent,
ContactComponent
],
providers: [
StringService,
ApiService,
UserService,
CookieService,
OrderService,
OrderGuard
],
bootstrap: [AppComponent],
exports: [
]
})
export class AppModule {
}
Binding the template variable #contactForm appears to cause a name conflict and blow up the template processor as it tries to turn the attached template variable into an NgForm on the backend. Everywhere I have seen model driven forms used there is no template variable binding on the form, whereas there is a #tv="ngForm" utilized in template driven forms. It appears there was a miss on the mixing of the two forms approaches which resulted in the error.
Simply removing it will resolve the issue.
When you incorrectly add to your template formGroup="..." instead of [formGroup]="..." you'll also get this error message.
It's been a while, but for me the problem was passing the formGroup to the template instead of referencing it directly.
E.g. this is not working
<ng-template #selectField
let-field
let-group
let-frmName="frmName">
<ng-container [formGroup]="group">
<mat-form-field fxFlex="32"
floatLabel="always">
<mat-label>{{field.label}}</mat-label>
<mat-select [formControlName]="frmName"
[required]="field.required">
<mat-option *ngFor="let option of field.options"
[value]="option.value">
{{option.description}}
</mat-option>
</mat-select>
</mat-form-field>
</ng-container>
</ng-template>
If I use directly my formGroup instance it works just fine.
Hope this helps.
I had a dynamic form. I got above error since I didn't init it inside the ngOnInit()
Solution:
checkInForm: FormGroup;
ngOnInit(){
this.checkInForm = this.formBuilder.group({});
}
Sometime this error is caused when you use a [formGroup] to pass the string of the formGroup name. Use formGroupName instead.
This can happen when you're using the input name formControl or formGroup on a custom component which isn't a form control.
Change your custom component to accept a different input name:
Change this
#Input()
formGroup: string
// ^ Causes issues
To this
#Input()
group: string
I forgot to pass my form to the reusable input <app-input [form]="myForm"></app-input>
app-input.component.html
<form [formGroup]="form">
<input [type]="type" [placeholder]="placeholder [formControlName]="formControlName" />
</form>
app-input.component.ts
#Input() type: string = '';
#Input() placeholder: string = '';
#Input() formControlName: string = ''
#Input() form: FormGroup = {} as FormGroup;