I have an angular form (not reactive).It has some required fields which get highlighted in red if empty during submission of the form. Now if I submit the form and then empty the required fields, still the fields get highlighted(even though the form is not submitted again) . Is there a way to not show this validation until the form is submitted again?
<form name="form" (ngSubmit)="f.form.valid && moveAsset()" #f="ngForm" novalidate>
<button type="submit" id="MoveAsset" name="MoveAsset" tabindex="214"
class="btn btn-primary pull-right" data-dismiss="modal"
[disabled]="assetMoveFieldAccessData['Move']">
{{fields['Move']}}
</button>
<div class="form-group required">
<label class="col-form-label control-label col-sm-4 for="site">
{{fields['Site']}}
</label>
<ng-select ngSelectSetTabindex [items]="siteList" name="siteid" id="siteid" tabindex="204"
(change)="siteChange()" bindLabel="siteName" bindValue="siteId" [(ngModel)]="site"
#siteid="ngModel" required placeholder="{{fields['Select Site']}}"
[ngClass]="{ 'invalid-errors-br': (f.submitted && (site == 0|| site == null || site ==
undefined))}" >
</ng-select>
</div>
</form>
Component:
myform: FormGroup;
#ViewChild('f', {static: true}) myForm;
public moveAsset(){
this.myForm.reset();
}
Related
I have an edit form as below which contains data in the input fields.
<ng-form #infoForm="ngForm" novalidate>
<div>
<label for="firstName">First Name :</label>
<input type="text"
class="form-control"
id="firstName"
name="firstName"
[(ngModel)]="in.firstName">
</div>
<div>
<label for="lastName">Last Name :</label>
<input type="text"
autocomplete="on"
class="form-control"
id="lastName"
name="lastName"
[(ngModel)]="in.lastName">
</div>
<button type="button" class="btn btn-primary" (click)="updateInfo(infoForm.value)">Update
</button>
</ng-form>
And I have the function in the component as below:
updateInfo(info: any) {
console.log(info);
}
This form return all the values (to the console) in the form when the Update button clicked, but I want to submit only the edited values instead of whole form. How could I implement it?
For this you can pass the form instead of its value to 'updateInfo' function and process it there. If user change the control value its state becomes 'dirty' from 'touched/pristine' and we can filter controls based on that.
Change in html:
<button type="button" class="btn btn-primary" (click)="updateInfo(infoForm)">Update
</button>
Change in *.ts file:
updateInfo(info: NgForm) {
const changedValues = Object.keys(info.controls)
.filter(key => info.controls[key].dirty === true)
.map(key => {
return { control: key, value: info.controls[key].value }
});
console.log(changedValues);
}
Background
I have a form where I give the user the option to specify either a quick time-frame or a detailed one (with a specific start/end time) - i.e. the user has the option to fill only one out of the two
The type of option that they wish to choose can be toggled with the click of a button. These buttons just toggle the hidden parameter on the specified divs
Issue
My problem here is that both of these fields (all 3 technically as start/end time are 2 separate form group divs under one generalized div) are required only if they are not hidden - I am not sure how this can be achieved with Angular 4/5/6 (using 6 here)
My invalid form trigger always goes off as the hidden field is also required
My Form
<div class="card-block">
<form #f="ngForm" (ngSubmit)="onSubmit(f)" novalidate>
<div class="form-group">
<label for="transactionType"> Request Type </label>
<select
class="form-control"
[(ngModel)]=data.transactionType
name ="transactionType"
#transactionType="ngModel"
required>
<option value="something1Count">Something1</option>
<option value="something2Count">Something2</option>
</select>
<div *ngIf="transactionType.errors?.required && transactionType.touched" class="alert alert-danger">
Please select a transaction type
</div>
</div>
<br>
<div class="form-group">
<label>Timeframe Type</label>
<br>
<button type="button" class="btn btn-light" (click)="quickTimeframe = false; detailedTimeframe = true;" ng-selected="!quickTimeFrame"> Quick </button>
<button type="button" class="btn btn-light" (click)="detailedTimeframe = false; quickTimeframe = true;" ng-selected="!detailedTimeframe"> Detailed </button>
</div>
<div class="form-group" [hidden]="quickTimeframe">
<label for="timeframe">Timeframe</label>
<select
class="form-control"
[(ngModel)]=data.timeframe
name ="timeframe"
#timeframe="ngModel"
required>
<option value="15">15 Minutes</option>
<option value="30">30 Minutes</option>
<option value="45">45 Minutes</option>
<option value="60">60 Minutes</option>
</select>
<div *ngIf=" !quickTimeframe && timeframe.errors?.required && timeframe.touched" class="alert alert-danger">
Please select a timeframe
</div>
</div>
<div class="detailed" [hidden]="detailedTimeframe">
<div class="form-group">
<label for="startTime">Start of Time Range</label>
<input
type="datetime-local"
class="form-control"
[(ngModel)]="data.startTime"
#startTime="ngModel"
name="startTime"
required
>
<div *ngIf="!detailedTimeframe && startTime.errors?.required && startTime.touched" class="alert alert-danger">
Please select a start-time
</div>
</div>
<div class="form-group">
<label for="endTime">End of Time Range</label>
<input
type="datetime-local"
class="form-control"
[(ngModel)]="data.endTime"
#endTime="ngModel"
name="endTime"
required
>
<div *ngIf="!detailedTimeframe && endTime.errors?.required && endTime.touched" class="alert alert-danger">
Please select an end-time
</div>
</div>
</div>
<input type="submit" class="btn btn-primary btn-block" value="Submit">
</form>
</div>
</div>
TS File
import { Component, OnInit } from '#angular/core';
import { Inputs } from '../../models/Inputs';
import { Router } from '#angular/router';
import {FlashMessagesService} from 'angular2-flash-messages';
#Component({
selector: 'app-main-form',
templateUrl: './main-form.component.html',
styleUrls: ['./main-form.component.css']
})
export class MainFormComponent implements OnInit {
data:Inputs = {
transactionType:'',
timeframe:null,
startTime:'',
endTime:''
};
quickTimeframe:boolean=true;
detailedTimeframe:boolean=true;
buttonResult:any;
constructor(public router:Router, public flashMessagesService:FlashMessagesService) {
}
ngOnInit() {
}
onSubmit({value, valid}:{value:Inputs, valid:boolean}){
console.log("Quick Time Flag: " +this.quickTimeframe);
console.log("Detailed Time Flag: " +this.detailedTimeframe);
if (valid && !this.quickTimeframe){
console.log("Form is valid");
//Stuff should happen
console.log(value);
} else if (valid && !this.detailedTimeframe) {
console.log(this.data.startTime);
//Other stuff should happen
}
else {
console.log("Form is not valid");
this.flashMessagesService.show('Choose Valid Parameters', {cssClass:'alert-danger', timeout: 4000});
}
}
radioClick() {
console.log(this.buttonResult);
}
}
Report Inputs Interface (for completion's sake)
export interface Inputs {
transactionType?:string;
timeframe?:number;
startTime?:string;
endTime?:string;
}
*ngIf did the trick
Using ngIf instead of hidden ensure that the elements do not exist within the form in my scenario
Here i'm using Angular2 i implement some html code for user access but why this data is not binding at Angular2 Source code side
Htmlcode
<form class="form-horizontal" novalidate [formGroup]="EmployeeForm">
<fieldset>
<div class="form-group" [ngClass]="{'has-error': (EmployeeForm.get('EmpName').touched ||
EmployeeForm.get('EmpName').dirty) &&
!EmployeeForm.get('EmpName').valid }">
<label for="name">Name</label>
<input type="text" class="form-control" formControlName="EmpName" [(ngModel)]="EmpName" />
<span>{{EmpName}}</span>
<span class="help-block" *ngIf="(EmployeeForm.get('EmpName').touched ||
EmployeeForm.get('EmpName').dirty) &&
EmployeeForm.get('EmpName').errors">
<span *ngIf="EmployeeForm.get('EmpName').errors.required">
Please enter your first name.
</span>
<span *ngIf="EmployeeForm.get('EmpName').errors.minlength || EmployeeForm.get('EmpName').errors.maxlength ||
EmployeeForm.get('EmpName').pattern">
The first name must be longer than A3 and max5 characters.
</span>
</span>
</div>
<button type="submit" class="btn btn-success" [disabled]="!EmployeeForm.valid" (click)="SaveDetails(EmployeeForm)">SaveDetails</button>
</fieldset>
</form>
component.ts
Here its pinging but data is not binding its showing as
zain = FormGroup {asyncValidator: null, _pristine: false, _touched: true, validator: function, _onCollectionChange: function…}
SaveDetails(Employee) {
}
try to change code from
<button type="submit" class="btn btn-success" [disabled]="!EmployeeForm.valid" (click)="SaveDetails(EmployeeForm)">SaveDetails</button>
to
<button type="submit" class="btn btn-success" [disabled]="!EmployeeForm.valid" (click)="SaveDetails(EmployeeForm.value)">SaveDetails</button>
i have tried with many ways:
Validation for select field angular 2
How to apply required validation to dropdown in angular 2
This help me to add validation in dropdown. but i have a issue that validation run properly but when i click on submit button it submit the form if dropdown value is valid or not. i do not want to submit my form if the value of dropdown is "select".
this is my HTML code:
<form name="form" (ngSubmit)="f.form.valid && SaveSymbol()" #f="ngForm" novalidate>
<div class="form-group" [ngClass]="{ 'has-error': f.submitted && !DisplayGroupID.valid && !manageSymbolViewModel.DisplayGroupID }">
<label for="DisplayGroupID">Display Group</label>
<select class="form-control" name="manageSymbolViewModel.DisplayGroupID" #DisplayGroupID id="manageSymbolViewModel.DisplayGroupID" [(ngModel)]="manageSymbolViewModel.DisplayGroupID" required>
<option value="0" selected disabled>Select</option>
<option *ngFor="let group of result.DisplayGroups" value={{group.DisplayGroupId}}>
{{group.DisplayGroup}}
</option>
</select>
<div *ngIf="f.submitted && !DisplayGroupID.valid && !manageSymbolViewModel.DisplayGroupID" class="help-block">Display Group is required</div>
</div>
<div class="form-group">
<button [disabled]="loading" type="submit" class="btn btn primary">Save</button>
<a [routerLink]="['/login']" class="btn btn-link">Cancel</a>
</div>
</form>
This is component code:
SaveSymbol() {
this.manageSymbolService.Save(this.manageSymbolViewModel).subscribe(data => {
debugger;
},
error => {
// this.alertService.error(error);
// this.loading = false;
});
}
}
The first and selected option of your select element has a value 0. So it basically it already has a value set to it on page load.
Try to change it to: <option value="" selected disabled>Select</option> and see if that fixes your problem.
Try this
<button [disabled]="loading || !DisplayGroupID.valid || !manageSymbolViewModel.DisplayGroupID" type="submit" class="btn btn primary">Save</button>
This will prevent the form from submitting while there is nothing selected in the dropdown or when the dropdown model is invalid.
please change your form as given below and also pass your status of form through submit function if required
<form #f="ngForm" (submit)="f.valid && SaveSymbol(f.value, f.valid)" novalidate>
<div class="form-group">
<label>Display Group</label>
<select ngControl="DisplayGroupID" #DisplayGroupID="ngForm" [(ngModel)]="manageSymbolViewModel.DisplayGroupID" required>
<option value='' disabled>Select</option>
<option *ngFor="let group of DisplayGroups" value={{group.DisplayGroupId}}>{{group.DisplayGroup}}</option>
</select>
<small [hidden]="DisplayGroupID.valid || (DisplayGroupID.pristine && !submitted)" class="text-danger">
Displaygroup is required
</small>
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
and initialise the model as
this.manageSymbolViewModel = {
DisplayGroupID: ''
};
refer this plunkr http://plnkr.co/edit/sFTM22xbZSXBLZcv90o2
If I'm reading your question right...
Your first value will be 0. So simply set your [disabled] attribute accordingly.
Example: [disabled]="loading || DisplayGroupId.value == 0"
Your button will not be enabled while the first option is selected. Simple solution.
I am using the model driven form like this .
Just like normal validations , i want that i show an error message if username and password are missing.
And Submit button should be disabled as long as username and password are not valid.
<div class="login">
<form #f="ngForm" (ngSubmit)="dologin(f)">
<div class="form-group">
<label for="username">Username</label>
<input id="username" type="text" class="form-control" name ="username" ngModel #username="ngModel">
<div [hidden]="username.valid" class="alert alert-danger"> Username is required.</div>
</div>
<div class="form-group">
<label for="password">Password</label>
<input id="password" type="password" class="form-control" name ="password" ngModel #password="ngModel">
<div [hidden]="password.valid" class="alert alert-danger"> Password is required.</div>
</div>
<button type="submit" [disabled]="username.length<0 || password.length<0" class="btn btn-primary" type="submit">Login</button>
</form>
</div>
i am seeing quite strange behaviour from validation div. Sometimes
it is showing "Password is required" and sometimes not.
i want to disable the submit button, until the form is valid .i tried
[disabled]="!f.valid"
but as i print it out f is always valid even
though i have not entered any data in username and password.
Component:
constructor(private router: Router,private authenticationService : AuthenticationService,private httpService:HttpService,private formBuilder:FormBuilder) {
this.form=formBuilder.group({
username:['',Validators.required],
password:['',Validators.required]
});
}
UPDATE
Can't bind to 'formGroup' since it isn't a known property of 'form'.
(" ][formGroup]="form"
(ngSubmit)="dologin(form.value)">
][formControl]="form.controls['password']">
[ERROR ->]
Username
[ERROR ->]
"): LoginComponent#4:8 No provider for NgControl ("
Password
[ERROR ->] ; Task: Promise.then ; Value:
Error: Template parse errors:(…) Error: Template parse errors: Can't
bind to 'formGroup' since it isn't a known property of 'form'. ("
][formGroup]="form"
(ngSubmit)="dologin(form.value)">
][formControl]="form.controls['password']">
[ERROR ->]
Username
[ERROR ->]
Thanks.
The way you have set up your HTML template is missing some key bits that actually ensure you have wired up the front end to the back end for a reactive form. What you have appears to be more in line with a template driven form mixed with model driven. In fact, the template you have posted will not even compile if you remove your FormsModule import.
To begin with remove your FormsModule import which is letting you mix the two different form types together. This will take us down a path where a strict Reactive Forms (aka model driven) implementation is required.
<form #f="ngForm" (ngSubmit)="dologin(f)"> will be changed to <form [formGroup]="form" (ngSubmit="dologin(form.value)"
Each of your inputs and warning divs will change from
<input id="username" type="text" class="form-control" name="username" ngModel #username="ngModel">
<div [hidden]="username.valid" class="alert alert-danger"> Username is required.</div>
To
<input id="username" type="text" class="form-control" name="username" formControlName="username">
The changes are because the ngModel attribute and #[name]="ngModel" are not supported in the model driven form, so instead you will use either formControlName or [formControl] syntax.
<div [hidden]="form.controls['username'].valid || form.controls['username'].pristine"
class="alert alert-danger"> Username is required.</div>
Finally, your submit button changes, note that you have type="submit" twice, from <button type="submit" [disabled]="username.length<0 || password.length<0" class="btn btn-primary" type="submit">Login</button>
To
<button type="submit" [disabled]="!form.valid" class="btn btn-primary">Login</button>
since we have successfully wired up the rest of the form the validation on the form group will now be correct
And here is a working plunker that you can play around with: https://plnkr.co/edit/Mu9vEYGB35SwUr9TEsPI?p=preview
Implementation without form builder
<form #loginForm="ngForm" (ngSubmit)="login()">
<md-input required type="email"
pattern="[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?"
placeholder="Email Address" #email="ngModel" name="email"
[(ngModel)]="loginModel.email"></md-input>
<div *ngIf="email.dirty && !email.valid && email.touched && email.errors" class="error-message">
<div *ngIf="email.errors.required">Email is required</div>
<div *ngIf="!email.errors.required && email.errors.pattern">This is not a valid email</div>
</div>
<md-input required type="password" placeholder="Password" #password="ngModel" name="password" [(ngModel)]="loginModel.password"></md-input>
<div *ngIf="password.dirty && !password.valid && password.touched && password.errors" class="error-message">
<div *ngIf="password.errors.required">Password is required</div>
</div>
<button ma-raised-button [disabled]="!loginForm.valid">
Login
</button>
</form>
Component:
ngOnInit() {
this.loginModel = {email: '', password: ''};
}
login() {
console.log(this.loginModel['email']);
console.log(this.loginModel['password']);
}