Angular library validator directive not working - javascript

I was trying to build an angular library for custom validator directive which can validate confirm password but as i build that library and publish on local npm and imported in my project it is throwing ERROR TypeError: tView is null error. here is codes
src\lib\confirm-password-validation.directive.ts
import { Directive } from '#angular/core';
import { FormGroup, NG_VALIDATORS, ValidationErrors, Validator } from '#angular/forms';
#Directive({
selector: '[appConfirmPasswordValidation]',
providers:[{
provide:NG_VALIDATORS,
useClass:ConfirmPasswordValidationDirective,
multi:true
}]
})
export class ConfirmPasswordValidationDirective {
constructor() {
console.log('Form Directive')
}
validate(form:FormGroup|any): ValidationErrors | null {
if(!form.controls.password || !form.controls.confirmPassword){
return null;
}
if(form.controls.password.errors && form.controls.confirmPassword.errors){
return null;
}
if(form.controls.password.value !== form.controls.confirmPassword.value){
form.controls.confirmPassword.setErrors({matchPassword:true});
return {matchPassword:true}
}
return null;
}
}
src\lib\confirm-password-validation.module.ts
import { NgModule } from '#angular/core';
import { ConfirmPasswordValidationComponent } from './confirm-password-validation.component';
import { ConfirmPasswordValidationDirective } from './confirm-password-validation.directive';
#NgModule({
declarations: [
ConfirmPasswordValidationComponent,
ConfirmPasswordValidationDirective
],
imports: [],
exports: [
ConfirmPasswordValidationComponent,
ConfirmPasswordValidationDirective
]
})
export class ConfirmPasswordValidationModule { }
src\public-api.ts
/*
* Public API Surface of confirm-password-validation
*/
export * from './lib/confirm-password-validation.service';
export * from './lib/confirm-password-validation.component';
export * from './lib/confirm-password-validation.module';
export * from './lib/confirm-password-validation.directive';
After publish i have installed in my project
src\app\app.module.ts
import { NgModule } from '#angular/core';
import { FormsModule, ReactiveFormsModule } from '#angular/forms';
import { BrowserModule } from '#angular/platform-browser';
import { ConfirmPasswordValidationModule } from 'confirm-password-validation';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
#NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule,
ReactiveFormsModule,
ConfirmPasswordValidationModule,
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
src\app\app.component.html
<div class="w-100 d-flex justify-content-center align-items-center" style="height: 100vh;">
<div class="card p-5">
<form [formGroup]="userForm" (ngSubmit)="submit()" appConfirmPasswordValidation>
<div class="mb-3 mt-3">
<label for="email" class="form-label">Email:</label>
<input type="email" class="form-control" id="email" placeholder="Enter email" formControlName="email">
</div>
<div class="mb-3">
<label for="pwd" class="form-label">Password:</label>
<input type="password" class="form-control" placeholder="Enter password" formControlName="password">
</div>
<div class="mb-3">
<label for="pwd" class="form-label">Confirm Password:</label>
<input type="password" class="form-control" placeholder="Enter password" formControlName="confirmPassword">
<p>
<span *ngIf="confirmPassword?.hasError('matchPassword')">
Password Mismatch
</span>
</p>
</div>
<div class="form-check mb-3">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" name="remember"> Remember me
</label>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
ERROR

Related

NG0301: Export of name 'ngModel' not found

in the below code i wanted to perform reactive form validation. so i referred to some questions and tutorial for example this one:
https://jasonwatmore.com/post/2018/05/10/angular-6-reactive-forms-validation-example
despite i followed the steps correctly, however when i run the App i receive the following errors
NG0301: Export of name 'ngModel' not found!
the respective spec file was modified as shown below and the required import add to the app.module.ts. please have a look at the code and files posted below and let me know how to fix this error
html code:
<div class="modal-body">
<form [formGroup]="distanceMeasuremrntForm" (ngSubmit)="measureDistanceForCoordinates()" #form="ngForm" class="clr-form clr-form-horizontal" autocomplete="off">
<clr-input-container>
<label >{{ "DISTANCE_MEASUREMENT.START_LONGITUDE" | translate }}:</label>
<input
id="startLngTextId"
required
maxlength="25"
clrInput
type="text"
name="name1"
[(ngModel)]=iMeasureDistanceParametersPasser.startLongitude
#name1="ngModel"
formControlName="startLngControlName"
[ngClass]="{ 'is-invalid': submitted && f.startLngControlName.errors }"
/>
<div *ngIf="submitted && f.startLngControlName.errors" class="invalid-startLng">
<div *ngIf="f.startLngControlName.errors.required">First Name is required</div>
</div>
</clr-input-container>
<clr-input-container>
<label>{{ "DISTANCE_MEASUREMENT.START_LATITUDE" | translate }}:</label>
<input
id="startLatTextId"
required
maxlength="25"
clrInput
type="text"
name="name2"
[(ngModel)]=iMeasureDistanceParametersPasser.startLatitude
#name2="ngModel"
formControlName="startatControlName"
[ngClass]="{ 'is-invalid': submitted && f.startatControlName.errors }"
/>
<div *ngIf="submitted && f.startatControlName.errors" class="invalid-startLat">
<div *ngIf="f.startatControlName.errors.required">First Name is required</div>
</div>
</clr-input-container>
<clr-input-container>
<label>{{ "DISTANCE_MEASUREMENT.END_LONGITUDE" | translate }}:</label>
<input
id="endLngTextId"
required
maxlength="25"
clrInput
type="text"
name="name3"
[(ngModel)]=iMeasureDistanceParametersPasser.endLongitude
#name3="ngModel"
formControlName="endLngControlName"
[ngClass]="{ 'is-invalid': submitted && f.endLngControlName.errors }"
/>
<div *ngIf="submitted && f.endLngControlName.errors" class="invalid-endLng">
<div *ngIf="f.endLngControlName.errors.required">First Name is required</div>
</div>
</clr-input-container>
<clr-input-container>
<label>{{ "DISTANCE_MEASUREMENT.END_LATITUDE" | translate }}:</label>
<input
id="endLatTextId"
required
maxlength="25"
clrInput
type="text"
name="name4"
[(ngModel)]=iMeasureDistanceParametersPasser.endLatitude
#name4="ngModel"
formControlName="endLatControlName"
[ngClass]="{ 'is-invalid': submitted && f.endLatControlName.errors }"
/>
<div *ngIf="submitted && f.endLatControlName.errors" class="invalid-endLat">
<div *ngIf="f.endLatControlName.errors.required">First Name is required</div>
</div>
</clr-input-container>
<div>
<button
class="btn btn-primary"
type="button"
>
{{ "DISTANCE_MEASUREMENT.ENTRY_LABEL" | translate }}
</button>
</div>
<div>
<button
class="btn btn-primary"
type="button"
(click)="clearInputs()"
>
{{ "COMMON.CLEAR_DATA" | translate }}
</button>
</div>
<div>
<label *ngIf=showMeasuredDistance>
{{ "DISTANCE_MEASUREMENT.DISTANCE" | translate }}
{{ "DISTANCE_MEASUREMENT.EQUAL" | translate }}
{{ mMeasuredDistanceInKM }}
{{ "DISTANCE_MEASUREMENT.UNIT_KM" | translate }}
</label>
</div>
</form>
<div class="modal-footer">
<button
class="btn btn-outline"
type="button"
(click)="hideWindowOverlay()"
>
{{ "COMMON.CANCEL" | translate }}
</button>
</div>
</div>
spec file:
import { ComponentFixture, TestBed } from '#angular/core/testing';
import { FormsModule } from '#angular/forms';
import { DistanceMeasurmentParametersComponent } from './distance-measurment-parameters.component';
describe('DistanceMeasurmentParametersComponent', () => {
let component: DistanceMeasurmentParametersComponent;
let fixture: ComponentFixture<DistanceMeasurmentParametersComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports:[FormsModule],
declarations: [ DistanceMeasurmentParametersComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(DistanceMeasurmentParametersComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
app module
import { BrowserModule } from "#angular/platform-browser";
import { NgModule } from "#angular/core";
import { AppComponent } from "./app.component";
#NgModule({
declarations: [
...
...
],
imports: [
BrowserModule,
HotTableModule.forRoot(),
FormsModule,//<-impored
.....,
.....,
ReactiveFormsModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
}
})
],
providers: [
{
provide: LocationStrategy,
useClass: HashLocationStrategy
},
{
provide: HTTP_INTERCEPTORS,
useClass: TokenInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: LoadingScreenInterceptor,
multi: true
}
],
bootstrap: [AppComponent]
})
export class AppModule {}
// AoT requires an exported function for factories
export function HttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http, './assets/i18n/', '.json');// für http://192.168.211.39/synops-2
//return new TranslateHttpLoader(http);
}

Why am I getting error: TypeError: "_co.form.submit is not a function"?

I'm trying to implement a Reactive Form that only submits when the submit button is clicked, not when the user hits Enter in an Input, but I'm getting TypeError: "_co.form.submit is not a function" and saw many similar questions such as submit is not a function and can't programmatically submit form, but none of the solutions worked (such as making sure the button is not named "submit"). I even made a small test app (code shown at bottom) which works fine, so I'm perplexed why my original app is having problems. The obvious difference between the code that works and doesn't work is that in the code that works I have #form template reference variable, but I took that out in the code that's having problems because including #form cause even more problems, such as TypeError: "this.form.get is not a function" and the form won't even render with #form in the element, whereas without it, at least the form renders even if it won't submit.
Here are excerpts from the code that is having problems:
details.component.html
<form class="member-wrapper" [formGroup]="form" method="POST" action="http://localhost:3000/users/{{route}}/details">
<div class="member-header">
<h3 class="member-title">{{(updating) ? 'Please update your details' : 'Share a bit about yourself'}}</h3>
<h4 class="member-description">Description</h4>
</div>
<div class="member-body">
. . .
. . .
</div>
<button type="button" (click)="form.submit()">Submit</button>
</form>
details.component.ts
import { Component, OnInit, AfterViewInit, ViewChildren, ElementRef, QueryList } from '#angular/core';
import { FormGroup, FormControl } from '#angular/forms';
import { TagDirective} from '../tag.directive';
. . .
. . .
export class DetailsComponent implements OnInit, AfterViewInit {
#ViewChildren(TagDirective) ipt!: QueryList<ElementRef>;
form: FormGroup = new FormGroup({});
got_data: boolean = false;
first_pass: boolean = true; updating: boolean = false;
data: Object;
meta: Object;
data_string: string;
datArr: any[] = [];
formCtls: any = {};
. . .
. . .
app.module.ts
import { NgModule, OnInit } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '#angular/forms';
. . .
. . .
import { AppComponent } from './app.component';
#NgModule({
imports: [
BrowserModule,
HttpClientModule,
FormsModule,
ReactiveFormsModule,
. . .
. . .
],
declarations: [
AppComponent,
. . .
. . .
],
details.module.ts (feature module for details component)
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import { FormsModule, ReactiveFormsModule } from '#angular/forms';
import { TagDirective } from '../tag.directive';
import { DetailsRoutingModule } from './details-routing.module';
import { DetailsComponent } from './details.component';
#NgModule({
declarations: [DetailsComponent, TagDirective],
imports: [
CommonModule,
DetailsRoutingModule,
FormsModule,
ReactiveFormsModule
]
})
export class DetailsModule { }
Here is the small test code that works fine:
test.component.html
<form #form [formGroup]="form" METHOD="GET" action="http://localhost:3000/test">
<input placeholder="Enter" formControlName="input1"/>
<input placeholder="The Dragon" formControlName="input2"/>
<button type="button" (click)="form.submit()">Submit</button>
</form>
test.component.ts
import { Component, OnInit } from '#angular/core';
import { FormGroup, FormControl } from '#angular/forms';
#Component({
selector: 'app-test',
templateUrl: './test.component.html',
styleUrls: ['./test.component.scss']
})
export class TestComponent implements OnInit {
form: FormGroup = new FormGroup({});
constructor() { }
ngOnInit() {
}
}
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { FormsModule, ReactiveFormsModule } from '#angular/forms';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { TestComponent } from './test/test.component';
#NgModule({
declarations: [
AppComponent,
TestComponent
],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule,
ReactiveFormsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Many thanks in advance if any ideas why I'm getting this error!
This line of code here is wrong
<button type="button" (click)="form.submit()">Submit</button>
This is how you can submit using reactive form using (ngSubmit)="onSubmit()"
Example
<form (ngSubmit)="onSubmit()" [formGroup]="loginForm">
<div class="form-group">
<label for="UserName">Your email</label>
<input
type="text"
class="form-control"
id="UserName"
name="UserName"
required
formControlName="UserName"
/>
<div
*ngIf="UserName.invalid && (UserName.dirty || UserName.touched)"
class="alert alert-danger"
>
<div *ngIf="UserName.errors.required">
Email is required
</div>
<div *ngIf="UserName.errors.whitespace">
whitespace is required
</div>
</div>
</div>
<div class="form-group">
<label for="password">Your password</label>
<input
type="password"
ngModel
class="form-control"
id="Password"
name="Password"
required
formControlName="Password"
/>
<div
*ngIf="Password.invalid && (Password.dirty || Password.touched)"
class="alert alert-danger"
>
<div *ngIf="Password.errors.required">
Password is required
</div>
</div>
</div>
<button type="submit" class="btn btn-success" [disabled]="!loginForm.valid">
Submit
</button>
</form>

ERROR TypeError: Cannot read property 'formData' of undefined

this is the error I'm getting in chrome:
UserComponent.html:7 ERROR TypeError: Cannot read property 'formData' of undefined
at Object.eval [as updateDirectives] (UserComponent.html:7)
at Object.debugUpdateDirectives [as updateDirectives] (core.js:23911)
at checkAndUpdateView (core.js:23307)
at callViewAction (core.js:23548)
at execComponentViewsAction (core.js:23490)
at checkAndUpdateView (core.js:23313)
at callViewAction (core.js:23548)
at execComponentViewsAction (core.js:23490)
at checkAndUpdateView (core.js:23313)
at callViewAction (core.js:23548)
I'm trying to do 2 way data binding with ngForm.
User.model.ts:
export class User {
Id: number;
UserName: string;
FullName: string;
MultipleRoles: string;
Status: string;
CreateDate: Date;
CreateBy: string;
}
User.service.ts:
import { Injectable } from '#angular/core';
import { User } from './user.model';
#Injectable({
providedIn: 'root'
})
export class UserService {
formData: User;
constructor() { }
}
user.component.html
<form #form = "ngForm">
<div class="form-group">
<label> USERNAME</label>
<input name="UserName" #UserName="ngModel" [(ngModel)]="UserService.formData.UserName" class="form-control">
</div>
<div class="form-group">
<label> FULLNAME</label>
<input name="FullName" #FullName="ngModel" [(ngModel)]="UserService.formData.FullName" class="form-control">
</div>
<div class="form-group">
<label> MULTIPLE ROLES</label>
<input name="MultipleRoles" #MultipleRoles="ngModel" [(ngModel)]="UserService.formData.MultiplesRoles" class="form-control">
</div>
<div class="form-group">
<label> STATUS</label>
<input name="Status" #Status="ngModel" [(ngModel)]="UserService.formData.Status" class="form-control">
</div>
<div class ="form-row">
<div class="form-group col-md-6">
<label> Create Date</label>
<input name="CreateDate" #CreateDate="ngModel" [(ngModel)]="UserService.formData.CreateDate" class="form-control">
</div>
<div class="form-group col-md-6">
<label> Create By</label>
<input name="CreateBy" #CreateBy="ngModel" [(ngModel)]="UserService.formData.CreateBy" class="form-control">
</div>
</div>
<div class="form-group">
<input type="button" value="SUBMIT" class="btn btn-lg btn-block">
</div>
</form>
user.component.ts:
import { Component,OnInit} from '#angular/core';
import { UserService } from 'src/app/shared/user.service';
import { FormsModule} from '#angular/forms';
import { FormGroup, FormControl} from '#angular/forms';
#Component({
selector: 'app-user',
templateUrl: './user.component.html',
styleUrls: ['./user.component.css']
})
export class UserComponent implements OnInit {
// constructor created to use user service class
constructor( private service: UserService) { }
ngOnInit() {
}
}
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppComponent } from './app.component';
import { UsersComponent } from './users/users.component';
import { UserComponent } from './users/user/user.component';
import { UserListComponent } from './users/user-list/user-list.component';
import { UserService } from './shared/user.service';
import { FormsModule} from '#angular/forms';
import { CommonModule } from '#angular/common';
#NgModule({
declarations: [
AppComponent,
UsersComponent,
UserComponent,
UserListComponent
],
imports: [
BrowserModule,
FormsModule,
CommonModule
],
providers: [UserService],
bootstrap: [AppComponent]
})
export class AppModule { }
I'm really really new in angular7 and trying to create a user form. Any help is much appreciated.
In UserService create an instance like this:
formData = new User();
and in UserService add private access modifier:
\/\/\/
constructor(private UserService: UserService) {
// code
}
Working_Demo
Update your constructor in user.component.ts with this
constructor(
public UserService: UserService
) { }

Angular - show/hide form based on action

I'm implementing a simple login/register app with Angular 4. What I want to achieve is to have the default view displaying the login form, and only when I click on a Register link I want to display the register form, that has to replace the login form.
Right now I have to click on the Login link to display it. I'll paste some code.
App Module
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { FormsModule } from '#angular/forms';
import { RouterModule } from '#angular/router';
import { AppComponent } from './components/app/app.component';
import { LoginComponent } from './components/login/login.component';
import { RegisterComponent } from './components/register/register.component';
import { HomeComponent } from './components/home/home.component';
import { UserService } from './services/user/user.service';
import { User } from './services/user/user';
#NgModule({
imports: [
BrowserModule,
FormsModule,
RouterModule.forRoot([
{
path: 'login',
component: LoginComponent
},
{
path: 'register',
component: RegisterComponent
},
{
path: 'home',
component: HomeComponent
}
])
],
declarations: [
AppComponent,
LoginComponent,
RegisterComponent,
HomeComponent
],
providers: [UserService, User],
bootstrap: [AppComponent]
})
export class AppModule { }
App Component Template
<div id="container">
<div id="parent">
<div id="left"></div>
<div id="right">
<nav>
<a routerLink="/login" routerLinkActive="active">Login</a>
<a routerLink="/register" routerLinkActive="active">Register</a>
</nav>
<router-outlet></router-outlet>
</div>
</div>
</div>
Login Component Template
<form #loginForm="ngForm" (ngSubmit)="onSubmit(loginForm)">
<div>
<label for="username">Username</label>
<input id="username" name="username" ngModel #username="ngModel">
</div>
<div>
<label for="password">Password</label>
<input id="password" name="password" ngModel #password="ngModel">
</div>
<span *ngIf="onSubmit(loginForm)">true</span>
<button>Login</button>
</form>
Register Component Template
<form #registerForm="ngForm" (ngSubmit)="onSubmit(registerForm)">
<div>
<label for="name">Nome</label>
<input id="name" name="name" ngModel #name="ngModel">
</div>
<div>
<label for="lastName">Cognome</label>
<input id="lastName" name="lastName" ngModel #lastName="ngModel">
</div>
<div>
<label for="username">Username</label>
<input id="username" name="username" ngModel #username="ngModel">
</div>
<div>
<label for="password">Password</label>
<input id="password" name="password" ngModel #password="ngModel">
</div>
<div>
<label for="passwordRep">Ripeti la password</label>
<input id="passwordRep" name="passwordRep">
</div>
<button>Registrati</button>
</form>
Is there some Router Module setting that I'm missing?
Thanks in advance.
In your routing you need to redirect the user to the login page if you want it as default view. So try the following:
RouterModule.forRoot([
{
path: '',
redirectTo: 'login',
pathMatch: 'full'
},
{
path: 'login',
component: LoginComponent
},
{
path: 'register',
component: RegisterComponent
},
{
path: 'home',
component: HomeComponent
}
])

I can't make an input be required with Angular2

I'm starting with Angular and I'm on a project where I have to validate the inputs so they can't be left clear, every input must me completed.
It's an html and we have a .ts file.
This is an extract of the html:
<div class="form-group">
<input type="text"
class="form-control"
id="factory"
[(ngModel)]="factory.company">
</div>
I need to validate this factory input but when I was watching tutorials all I needed to do was to write 'required' inside the <input> and that was it but I had a <form> and every input was inside this form, and this html doesn't have a <form> and when I put one the design was horrible and I couldn't work.
Here is an example using required fields (in login page) :
<form [formGroup]='loginForm' (submit)="login(loginForm.value)">
<div class="col-md-6">
<div class="login-mail">
<input type="text" placeholder="Email" formControlName="email" required="">
<i class="fa fa-envelope"></i>
</div>
<div class="login-mail">
<input type="password" placeholder="Password" formControlName="password" pattern=".{8,20}" required="">
<i class="fa fa-lock"></i>
</div>
</div>
<div class="col-md-6 login-do">
<label class="hvr-shutter-in-horizontal login-sub">
<input type="submit" value="login" >
</label>
</div>
<div class="clearfix"> </div>
</form>
in the login.component.ts , u should make some changes:
1) import some modules :
import { FormBuilder, FormGroup, Validators} from '#angular/forms';
2) in oninit function :
loginForm: FormGroup;
constructor(private fb : FormBuilder) {}
ngOnInit(){
this.loginForm = this.fb.group({
email : ["", Validators.required],
password : ["", Validators.required]
});
}
Hope that helps u :)
I would think that you should be able to add a form element. However, if you cannot as you have said then you can add the ngForm directive onto any element to achieve the same behavior as having the form element.
See this plunker for examples using ReactiveFormsModule and FormsModule:
Plunker
//our root app component
import {Component, OnInit, NgModule} from '#angular/core'
import {ReactiveFormsModule, FormsModule, FormControl, Validators} from '#angular/forms'
import {BrowserModule} from '#angular/platform-browser'
#Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}}</h2>
<div class="form-group">
<label>Model Driven Form</label>
<input type="text"
class="form-control"
id="companyModel"
[formControl]="companyModel">
<span [hidden]="companyModel.valid || companyModel.pristine">REQUIRED!</span>
</div>
<div class="form-group" ngForm #myForm="ngForm">
<label>Template Driven Form</label>
<input type="text"
class="form-control"
name="companyTemplate"
ngModel
id="companyTemplate"
#companyTemplate="ngModel"
required>
<span [hidden]="companyTemplate.valid || companyTemplate.pristine">REQUIRED!</span>
</div>
</div>
`,
})
export class App implements OnInit {
name:string;
companyModel: FormControl
constructor() {
this.name = 'Form Validation Demo'
}
ngOnInit() {
this.companyModel = new FormControl('', Validators.required)
}
}
#NgModule({
imports: [ BrowserModule, ReactiveFormsModule, FormsModule ],
declarations: [ App ],
bootstrap: [ App ]
})
export class AppModule {}

Categories