Reactive Form validation not working - javascript

I have created a component for user signup
import { Component } from '#angular/core';
import {UserManagementService} from '../user-management.service';
import {User} from "../user";
import {FormBuilder, FormGroup,Validators} from "#angular/forms";
#Component({
selector: 'app-signup-component',
templateUrl: './signup-component.component.html',
styleUrls: ['./signup-component.component.css'],
providers:[UserManagementService]
})
export class SignupComponentComponent {
newUser:User;
signupForm:FormGroup;
constructor(private userManagementService: UserManagementService, private fb:FormBuilder) {
this.createForm();
}
createForm(){
this.signupForm = this.fb.group({
firstName:['',Validators.required],
lastName:['',Validators.required],
email:['',Validators.required],
password:['',Validators.required]
});
}
addUser(){
this.newUser = new User({
firstname:this.signupForm.get('firstName').value,
lastname:this.signupForm.get('lastName').value,
email:this.signupForm.get('email').value
});
console.log("in SignupComponentComponent: addUser: "+this.newUser);
this.userManagementService.addUser(this.newUser);
}
}
Following is the template
<div class="div__signup">
<div class="content_div--white">
<form class="signup-form" [formGroup]="signupForm" (ngSubmit)="addUser()" novalidate>
<label for="firstname" class="first-name">First Name</label>
<input id="firstname" type="text" class="form-control" formControlName="firstName" required>
<label for="lastname" class="last-name">Last Name</label>
<input id="lastname" type="text" class="form-control" formControlName="lastName" required>
<label for="email" class="email"> Email</label>
<input id="email" type="email" class="form-control" formControlName="email" required>
<label for="password" class="password">Password</label>
<input id="password" type="password" class="form-control" formControlName="password" required>
<label for="verify-password" class="verify-password">Verify Password</label>
<input id="verify-password" type="password" class="form-control" required>
<button type="submit" id="signup-button" class="content-div__button--blue"> Sign Up! </button>
</form>
</div>
</div>
UserManagementService is
import { Injectable } from '#angular/core';
import {User} from './user';
#Injectable()
export class UserManagementService {
constructor() { }
addUser(user:User){
console.log("In UserManagementService: addUser: "+user)
}
}
Even if I submit the form withtou any data (all input empty), I see the following two console messages
in SignupComponentComponent: addUser: [object Object]
In UserManagementService: addUser: [object Object]
It seems the Validators are not working (I must not be using them correctly). Why does the UserManagementService gets called. Shouldn't Angular not submit the form if there are errors in the form?

Here you go :
addUser(){
if (this.signupForm.valid) {
this.newUser = this.signupForm.value;
console.log("in SignupComponentComponent: addUser: ", this.newUser);
this.userManagementService.addUser(this.newUser);
}
}
<button type="submit" [disabled]="signupForm.invalid" id="signup-button" class="content-div__button--blue"> Sign Up! </button>
You first need to test if the form is valid. Angular lets you submit the form even if it's invalid, so that you can make something of your own (for instance, display an error message).
You also can shorten your code by getting the value of the form directly, instead of re-creating the user like you did.
You can also deactivate your button if your form is invalid, so that the user can't send the form.

Related

Prepopulate the existing values in the form field in Angular

I want to update existing data information using update data form. The input should populate the existing values. How to do that?
As of now, I have to enter all the fields manually to update the form.
Update doctor .ts file
import { Component, OnInit } from '#angular/core';
import { FormArray, FormBuilder, FormControl, FormGroup } from '#angular/forms';
import { ActivatedRoute, Router } from '#angular/router';
import { Doctor } from '../doctor';
import { DoctorService } from '../doctor.service';
#Component({
selector: 'app-update-doctor',
templateUrl: './update-doctor.component.html',
styleUrls: ['./update-doctor.component.css']
})
export class UpdateDoctorComponent implements OnInit {
id:any;
doctor:Doctor;
updateForm:FormGroup;
constructor(private route: ActivatedRoute, private router: Router,private doctorservice: DoctorService,private formbuilder:FormBuilder) {
}
ngOnInit() {
this.doctor = new Doctor();
}
updateDoctor(){
this.doctorservice.updateDoctor( this.doctor)
.subscribe(data =>{
console.log(data);
this.doctor = new Doctor();
window.location.reload();
})
this.gotoList();
}
onSubmit(){
this.updateDoctor();
}
gotoList() {
this.router.navigate(['doctor']);
}
}
update doctor .html file
<div class="card col-md-4 offset-md-4 mt-3" >
<h3>Update Doctor</h3>
<div style="width: 100% ;">
<form (ngSubmit)="onSubmit()">
<div class="form-group">
<label for="doctorId"> Id</label>
<input type="text" class="form-control" id="doctorId" required [(ngModel)]="doctor.doctorId" name="doctorId" #doctorId>
</div>
<div class="form-group">
<label for="doctorName"> Name</label>
<input type="text" class="form-control" id="doctorName" value="{{doctor.doctorName}}" required [(ngModel)]="doctor.doctorName" name="doctorName" #doctorId>
</div>
<div class="form-group">
<label for="doctorProfile">Profile</label>
<input type="text" class="form-control" id="doctorProfile" required [(ngModel)]="doctor.doctorProfile" name="doctorProfile">
</div>
<div class="form-group">
<label for="doctorSpeciality">Speciality</label>
<input type="text" class="form-control" id="doctorSpeciality" value="{{doctor.doctorSpeciality}}" required [(ngModel)]="doctor.doctorSpeciality" name="doctorSpeciality">
</div>
<div class="form-group">
<label for="doctorQualification">Qualification</label>
<input type="text" class="form-control" id="doctorQualification" value="{{doctor.doctorQualification}}" required [(ngModel)]="doctor.doctorQualification" name="doctorQualification">
</div>
<div class="form-group">
<label for="doctorEmail">Email</label>
<input type="text" class="form-control" id="doctorEmail" value="{{doctor.doctorEmail}}" required [(ngModel)]="doctor.doctorEmail" name="doctorEmail">
</div>
<div class="form-group">
<label for="doctorPassword">Password</label>
<input type="password" class="form-control" id="doctorPassword" required [(ngModel)]="doctor.doctorPassword" name="doctorPassword">
</div>
<button type="submit" class="btn btn-dark">Submit</button>
</form>
</div>
</div>
From this function I am navigating to update doctor form
updateDoctor(){
this.router.navigate(['update'])
}
service method for update.
updateDoctor(doctor:Object):Observable<Object>{
return this.http.put(`${this.baseUrl1}`,doctor);
}
You could write a service to get the existing form data and load the data in the form through this.doctor object on load.

When using template driven forms in Angular 2, how to access the form in the component?

I have a simple template driven form like so:
HTML:
<div class="container">
<h1>Hero Form</h1>
<form (ngSubmit)="onSubmit()" #heroForm="ngForm">
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" id="name" [(ngModel)]="model.name" name="name" #name="ngModel">
</div>
<div class="form-group">
<label for="alterEgo">Alter Ego</label>
<input type="text" class="form-control" id="alterEgo" [(ngModel)]="model.alterEgo" name="alterEgo">
</div>
<div class="form-group">
<label for="power">Hero Power</label>
<select class="form-control" id="power" [(ngModel)]="model.power" name="power">
<option *ngFor="let pow of powers" [value]="pow">{{pow}}</option>
</select>
</div>
<button type="submit" class="btn btn-success" [disabled]="!heroForm.form.valid">Submit</button>
</form>
</div>
Component:
import { Component, OnInit } from '#angular/core';
import { Hero } from './hero';
#Component({
selector: 'at-hero',
templateUrl: './hero.component.html',
styleUrls: ['./hero.component.scss']
})
export class HeroComponent implements OnInit {
constructor() {
//
}
ngOnInit() {
//
}
powers = ['Really Smart', 'Super Flexible', 'Super Hot', 'Weather Changer'];
model = new Hero(18, 'Dr IQ', this.powers[0], 'Chuck Overstreet');
submitted = false;
onSubmit() { this.submitted = true; }
newHero() {
this.model = new Hero(42, '', '');
}
}
How can I:
Reset the whole form from the component (not from the markup)?
Reset a single form field (e.g. the name field) also from the component and not the markup?
You can get the form by using ViewChild
Markup
<form (ngSubmit)="onSubmit()" #heroForm="ngForm">
...
</form>
Component
#ViewChild('heroForm') public heroForm: NgForm;
I suggest you also to look at Reactive Forms too. I think this will be more handy if you want to work with form in the typescript, not in the markup

how to get value from html form and pass is to typescript in angular

Do anyone know how can I get value from HTML forms in typescript?
this is how my html page: login.component.html
<form [formGroup]="loginForm" id="loginForm" (ngSubmit)="authUser()" #userForm="ngForm">
<div class="container">
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
<p><input type="email" formControlName="email" id="email" placeholder="Your email" [(ngModel)]="user.email" required></p>
</div>
</div>
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
<p><input type="password" formControlName="password" id="password" placeholder="Your password" [(ngModel)]="user.password" required></p>
</div>
</div>
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
<p><button class="btn btn-primary" type="submit" [disabled]="!bookForm.form.valid">Login</button> </p>
</div>
</div>
</div>
</form>
<div *ngIf="edited" class="alert alert-success box-msg" role="alert">
<strong>Successful Login!</strong>
</div>
and this is my typescript: login.component.ts
import { Component, OnInit } from '#angular/core';
import { FormBuilder, FormGroup } from '#angular/forms';
import { Router } from '#angular/router';
import { Http } from '#angular/http';
import { PostsService } from '../posts.service';
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
loginForm: FormGroup;
login = false;
users: any;
user = {};
constructor(private fb: FormBuilder, private http: Http, private router: Router, private postsService: PostsService) {
this.postsService.getAllPosts().subscribe(users => {
this.users = users;
});
}
ngOnInit() {
this.loginForm = this.fb.group({
email: 'a#b.com',
password: 'abc123.'
});
}
authUser() {
var i:number;
var email:string = this.loginForm.value.email;
var password:string = this.loginForm.value.password;
var userType:string;
var userEmail:string;
for(i=0;i<this.users.length;i++){
if(this.users[i].email == email && this.users[i].password == password){
this.login = true
userEmail = this.users[i].email;
userType = this.users[i].accountType;
}
}
if(this.login){
console.log("Sucessful");
}
else{
console.log("Unsucessful");
}
}
}
I have tried a lot of methods but none of them seems to work for now my login the way my code words is that once the button is press it will not check whats in the html forms. but it will check againce var email:string = this.loginForm.value.email; and my database for the email and the value thats in var email:string = this.loginForm.value.email; have been hardcoded.
You can try to get value from your ngModel and use .find function to filter your data it's easy and fast to get user details
public userType: string;
public userEmail:string;
public loginUser:any;
authUser() {
this.loginUser = this.users.find(x => x.email == this.user.email && x.password == this.user.password);
if(this.loginUser){
this.login = true
this.userEmail = this.loginUser.email;
this.userType = this.loginUser.accountType;
}
}
You need the prevent default behavior of form. Use following code in your authUser method:
authUser(event) {
event.preventDefault();
//rest of code
}
and update your form tag:
<form [formGroup]="loginForm" id="loginForm" (ngSubmit)="authUser($event)" #userForm="ngForm">
1.- don't mix Reactive form and Template forms.
//with ReactiveForm
<input type="password" formControlName="password" id="password" placeholder="Your password" >
//with template Drive Form
<input type="password" id="password" placeholder="Your password" [(ngModel)]="user.password" required>
2.- with Template driven Form you must have
this.user:any={
email: 'a#b.com',
password: 'abc123.'
}
//And in the submit function you have this.user.email and this.user.password
3.- with Reactive Form
//the validators it's included when create the fbgroup
this.loginForm = this.fb.group({
email: ['a#b.com',Required]
password: ['abc123.',Required]
});
//in the submit pass loginForm as argument
<form [formGroup]="loginForm" id="loginForm" (ngSubmit)="authUser(loginForm)">
//then in your authUser
authUser(form:any){
if (form.valid)
{
console.log(form.value.email,form.value.password)
}
}
4.-You're checking email and password compared with a list of users, but you really have not a list of users. if really post.Service.getAllPost get a list of users the method have a "very bad" name. Ah! put the subscribe in a ngOnInit, not in de constructor
ngOnInit()
{
this.postsService.getAllPosts().subscribe(users => {
this.users = users;
});
....
}

Creating an add button for dynamic fields not working

I am trying to create a dynamic field with an add button and a delete button with the Address class. I am stuck as to why the addAddress function does not work. I searched around for a solution but nothing I have searched has worked. I am a novice with Angular so I might be making this more complicated then it needs to be. Here is the app.component.ts
import { FormGroup, FormControl, FormArray, FormBuilder } from
'#angular/forms';
import { Component, OnInit } from '#angular/core';
import { Validators} from '#angular/forms';
class Address{
constructor(public stName, public aptNo, public pinCode){
}
}
class registrationModel{
constructor(public firstName, public lastName,public age,public fromStates,
public state, public homeAddress:Array<Address> ){}
}
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
private _formObject:FormGroup;
private _formModel:registrationModel;
private _addressObject:Address;
private _createFormGroup(){
this._formObject = this._formBuilder.group({
addLabelTitle:["", Validators.minLength(2)],
addLabelType:["", Validators.minLength(2)],
firstName:[],
lastName:[],
age:[18, [Validators.min(18), Validators.max(60)]],
fromStates:[false],
state:[],
stName: [],
aptNo: [],
pinCode: [],
homeAddress:this._formBuilder.array([Address])
});
this._formObject.reset(this._formModel);
console.info(this._formObject);
}
private _submitValue(){
// this._formObject = this._formBuilder.group({
// addLabelTitle:[],
// addLabelType:[],
// firstName:[],
// lastName:[],
// age:[],
// fromStates:[false],
// state:[]
// });
console.info(this._formObject.value);
}
private _resetValue(){
this._formObject.reset();
}
private _addAddress(){
this._addressObject = new Address("","","");
/*
Create a address model.
Inject it to formObject.
*/
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<small>{{this._formObject.value|json}}</small>
<!--The content below is only a placeholder and can be replaced.-->
<div class="registrationForm" [formGroup]="_formObject">
<!-- Name Input box -->
<div class="formGroup">
<label>Name :</label>
<input type="text" placeholder="First Name" formControlName="firstName"
ngModel required>
<input type="text" formControlName="lastName" placeholder="Last Name"
ngModel required>
</div>
<!-- Name Age box -->
<div class="formGroup">
<label>Age :</label>
<input type="number" placeholder="Age" formControlName="age">
<small *ngIf="_formObject.controls.age.errors">
{{getErrors(_formObject.controls.age.errors)}}</small>
</div>
<!-- form United States -->
<div class="formGroup">
<label>From United States </label>
<input type="checkbox" formControlName="fromStates" ngModel required>
</div>
<!-- States -->
<div class="formGroup">
<label>States :</label>
<select formControlName="state">
<option value="co">Colordo</option>
<option value="ca">California</option>
</select>
</div>
<div class="formGroup">
<label>formControlName </label>
<select formControlName="state">
<option value="co">Colordo</option>
<option value="ca">California</option>
</select>
</div>
<hr/>
<div formArrayName="homeAddress">
<button>Delete</button>
<div *ngFor="let address of this._formObject.controls.homeAddress.controls;
let i=index">
<div [formGroupName]="i">
<div class="formGroup">
<label>St Name :</label>
<input type="text" placeholder="" formControlName="stName" ngModel
required>
</div>
<div class="formGroup">
<label>Apt Number :</label>
<input type="text" placeholder="" formControlName="aptNo" ngModel
required>
</div>
<div class="formGroup">
<label>Pincode :</label>
<input type="text" placeholder="" formControlName="pinCode" ngModel
required>
</div>
<!-- <div class="formGroup">
<label>Add Label: </label>
<input type="text" placeholder="Label Title"
formControlName="addLabelTitle">
<input type="text" placeholder="Type (Text, Checkbox, etc)"
formControlName="addLabelType">
</div>
-->
</div>
<hr/>
</div>
<div class="formGroup text-center">
<button (click)="_addAddress()">Add address</button>
<!-- Submit -->
<button (click)="_submitValue()">Submit</button>
<!-- Cancel -->
<button (click)="_resetValue()">Cancel</button>
</div>
</div>
You need to add a formgroup to your form array, if you like to use the class Address you have, you can do it by
_addAddress() {
let formArr = this._formObject.controls.homeAddress;
formArr.push(this._formBuilder.group(new Address('','','')))
}
You can remove all ngModel and required from your form, these belong with template driven forms.
The build of the form is I would create an empty FormArray, and then just call _addAddress after the build of the form since you probably want an initial formgroup in your form array.
As a sidenote, I can't see that the following would even work (?)
homeAddress:this._formBuilder.array([Address])
So I would scrap that and do:
_createFormGroup(){
this._formObject = this._formBuilder.group({
// all other form controls here
homeAddress:this._formBuilder.array([])
});
this._addAddress();
}

Angular 2 error- There is no directive with "exportAs" set to "ngModel" with RC4 version

I am using angular 2 forms in my application and i have created the forms based on given link.
https://angular.io/docs/ts/latest/guide/forms.html
In this for validation and to use forms APIs, i have set the ngModel values like #name="id" #id="ngModel" and which throws script error. But its resolved if i set #id="ngModel" as #id="ngForm". But for my case i have to set my model value to ngModel.
Below is my html page.
<form (ngSubmit)="onSubmit()" #myForm="ngForm">
<div class="form-group">
<label class="control-label" for="id">Employee ID</label>
<input type="text" class="form-control" required [(ngModel)]="model.id" #name="id" #id="ngModel" >
<div [hidden]="id.valid || id.pristine" class="alert alert-danger">
Employee ID is required
</div>
</div>
<div class="form-group">
<label for="name">Employee Name</label>
<input type="text" class="form-control" [(ngModel)]="model.name" name="name" #name="ngModel" required>
<div [hidden]="name.valid || name.pristine" class="alert alert-danger">
Employee ID is required
</div>
</div>
<div class="form-group">
<label for="DOJ">DOJ</label>
<input class="form-control" required [(ngModel)]="model.DOJ" name="DOJ" #DOJ="ngModel" />
<div [hidden]="DOJ.valid || DOJ.pristine" class="alert alert-danger">
DOJ is required
</div>
</div>
<button type="submit" class="btn btn-default" [disabled]="!myForm.form.valid">Submit</button>
</form>
Below is my issue.
EXCEPTION: Template parse errors:
There is no directive with "exportAs" set to "ngModel" ("
<div>
<h1>My Form</h1>
<form (ngSubmit)="onSubmit()" [ERROR ->]#myForm="ngModel">
<div class="form-group>
<label class="control-label" for="id">Employee"):AppComponent#3:34
I have checked with more questions and answers, most of them said to update angular2 version to RC4 so i have updated my application to rc4 but still i am facing this issue.
Below is my ts file:
import {Component} from '#angular/core';
import { disableDeprecatedForms, provideForms , NgForm} from '#angular/forms';
import {CORE_DIRECTIVES, FORM_DIRECTIVES, FormBuilder,Validators,Control,ControlGroup } from '#angular/common';
#Component({
selector: 'ej-app',
templateUrl: 'app/app.component.html',
directives: [ CORE_DIRECTIVES,FORM_DIRECTIVES]
})
export class AppComponent {
model = new Employees(null,'','');
onSubmit() { alert("values submitted")}
constructor() {
}
}
export class Employees {
constructor( public id: number,public name: string, public DOJ: String ) { }
}
Do not import the FORM_DIRECTIVES and CORE_DIRECTIVES because they are deprecated, instead make sure that you import the NgForm. You can use the following:
import {FormGroup, FormBuilder, FormControl, Validators, NgForm } from '#angular/forms';
Don't mix the new and old forms module.
import {CORE_DIRECTIVES, FORM_DIRECTIVES, FormBuilder,Validators,Control,ControlGroup } from '#angular/common';
imports forms stuff from #angular/common. If you use the new forms
bootstrap(AppComponent, [disableDeprecatedForms(), provideForms()])
then use instead
import {FORM_DIRECTIVES, FormBuilder,Validators,Control,ControlGroup } from '#angular/forms';

Categories

Resources