Hi I am trying to validate toggle switch in Angular 5. If the user selects off then i want to display error message. But when user clicks on submit button(form submission) I am not able to validate if the toggle is off. In below step I want to validate on submit button.
<form *ngIf="formResetToggle" class="form-horizontal" name="permissionEditorForm" #f="ngForm" novalidate
(ngSubmit)="f.form.valid ? savePermission(selectedUserRole.value,selectedScopeName.value) :
(!userrole.valid && !scopename.valid && showErrorAlert('Please enter mandatory fields'));">
<div class="form-group has-feedback">
<label class="control-label col-md-2"for="allowdeny">Allow/Deny</label>
<div class="col-md-10">
<ui-switch checked size="small" [(ngModel)]="permissionEdit.isallowed" name="isallowed" id="isallowed"></ui-switch>
<span *ngIf="IsAllowed" class="errorMessage">
Is Allowed should be true!
</span>
</div>
</div>
</form>
In the above code, If I do something
(ngSubmit)="f.form.valid ? savePermission(selectedUserRole.value,selectedScopeName.value) :
(!userrole.valid && !scopename.valid && !isallowed.valid && showErrorAlert('Please enter mandatory fields'));"
then I get error in !isallowed.valid. The error message says cannot read property of undefined valid. can someone help me to make above validation works? Any help would be appreciated. Thank you.
Related
I am trying to create a custom register view/form and have it work with auth.register(), but so far I've had no luck. I mainly have two problems.
If I don't include response.view = 'register.html' in my controller the link register.html defaults to web2py's default register page (which works, but I don't want to use).
If I removed the response.view = 'register.html' from my controller func, then my custom form/view appears, but doesn't submit/validate. It just keeps popping the on-fail message "Oops something went wrong submitting the form"
Every thread I've read about this just says to specify the form=auth.register() in the controller and use the {{=form.custom.end}} in the view, but that doesn't seem to work. Am I missing something?
I also tried specifying the callback action for the form to action="{{=URL('default', 'register')}}, but if I add this the page won't do anything on submit either.
Here's my code:
Controller: (In default.py)
def register():
response.view = 'register.html'
db.auth_user.first_name.readable = db.auth_user.first_name.writable = False
db.auth_user.last_name.readable = db.auth_user.last_name.writable = False
return dict(form=auth.register())
View (default/register.html)
<body class="body-4">
<div class="form-block w-form">
<form id="email-form" name="email-form" data-name="Email Form">
<h1 class="heading-5">Register</h1>
<input type="email" class="text-field w-input" maxlength4="256" name="Email" data-name="Email" placeholder="Enter your email" id="Email" required="">
<input type="password" class="text-field w-input" maxlength="256" name="Password" data-name="Password" placeholder="Enter your password" id="Password" required="">
<input type="password" class="text-field w-input" maxlength="256" name="Password-2" data-name="Password 2" placeholder="Confirm your password" id="Password-2" required="">
<input type="submit" value="Register" data-wait="Please wait..." class="submit-button w-button">
{{=form.custom.end}}
<div class="w-form-done">
<div>Thank you! Your submission has been received!</div>
</div>
<div class="w-form-fail">
<div>Oops! Something went wrong while submitting the form.</div>
</div>
</div>
<script src="{{=URL('static','js/webflow.js')}}" type="text/javascript"></script>
<!-- [if lte IE 9]><script src="https://cdnjs.cloudflare.com/ajax/libs/placeholders/3.0.2/placeholders.min.js"></script><![endif] -->
</body>
You need to put the viewer code into the file default/register.html instead of register.html .
Then it works for me. You can see the resulting entry in the database.
I am working on angular 4 project. In which, I used reactive forms and angular validations. All the validation messages are shown on focus out of field. But I want to show validation messages on submit button also.
Html Code:
<form [formGroup] = "addNewCustomerForm" (ngSubmit) = "submitAddNewCustomerForm()">
<div class="form-group">
<label>First Name</label>
<input class="form-control" [class.alert-border]="addNewCustomerForm.controls['first_name'].hasError('required') && addNewCustomerForm.controls['first_name'].touched" placeholder="Ex: James" formControlName="first_name">
</div>
<small *ngIf="addNewCustomerForm.controls['first_name'].hasError('required') && addNewCustomerForm.controls['first_name'].touched" class="required alert-error"><i class="material-icons">error</i> Please enter a valid first name.</small>
<small *ngIf="addNewCustomerForm.controls['first_name'].hasError('pattern') && addNewCustomerForm.controls['first_name'].touched && !addNewCustomerForm.controls['first_name'].hasError('required')" class="patern alert-error"><i class="material-icons">error</i> Please enter a valid first name.</small>
<div class="form-group">
<label>Last Name</label>
<input class="form-control" [class.alert-border]="addNewCustomerForm.controls['last_name'].hasError('required') && addNewCustomerForm.controls['last_name'].touched" placeholder="Ex: Lee" formControlName="last_name">
</div>
<small *ngIf="addNewCustomerForm.controls['last_name'].hasError('required') && addNewCustomerForm.controls['last_name'].touched" class="required alert-error"><i class="material-icons">error</i> Please enter a valid last name.</small>
<small *ngIf="addNewCustomerForm.controls['last_name'].hasError('pattern') && addNewCustomerForm.controls['last_name'].touched && !addNewCustomerForm.controls['last_name'].hasError('required')" class="patern alert-error"><i class="material-icons">error</i> Please enter a valid last name.</small>
<div class="form-group">
<label>Email Address</label>
<input class="form-control" [class.alert-border]="addNewCustomerForm.controls['email_id'].hasError('required') && addNewCustomerForm.controls['email_id'].touched" placeholder="Ex: example#xyz.com" formControlName="email_id" (focusin)="emailExist = false" (focusout)="checkEmailExistance($event)">
</div>
<small *ngIf="addNewCustomerForm.controls['email_id'].hasError('required') && addNewCustomerForm.controls['email_id'].touched" class="required alert-error"><i class="material-icons">error</i> Please enter a valid email.</small>
<small *ngIf="addNewCustomerForm.controls['email_id'].hasError('pattern') && addNewCustomerForm.controls['email_id'].touched && !addNewCustomerForm.controls['email_id'].hasError('required')" class="patern alert-error"><i class="material-icons">error</i> Please enter a valid email.</small>
<small *ngIf="emailExist" class="alert-error"><i class="material-icons">error</i> This email already exists. Please try with different email.</small>
</form>
ts code:
this.addNewCustomerForm = this.formGroup.group({
first_name : [null, [Validators.required, Validators.pattern(this.regExpression)]],
last_name : [null, [Validators.required, Validators.pattern(this.regExpression)]],
email_id : [null, [Validators.required, Validators.pattern(this.emailPattern)]] });
submitAddNewCustomerForm(){
if(this.addNewCustomerForm.valid)
{
console.log(this.addNewCustomerForm.value);
}
}
Well you have two options,
One :- have a Boolean variable in your submit function and set true in case if form is invalid and use that in your error block's ngIf condition.
Below is an example of the same.
submitAddNewCustomerForm(){
if(this.addNewCustomerForm.invalid)
{
this.showError = true;
}
}
And in html error
<small *ngIf="(showError || (addNewCustomerForm.controls['last_name'].hasError('pattern') && addNewCustomerForm.controls['last_name'].touched)) && !addNewCustomerForm.controls['last_name'].hasError('required')" class="patern alert-error"><i class="material-icons">error</i> Please enter a valid last name.</small>
And Second option is you mark each control dirty by using
this.controlName.markAsDirty()
Or by
this.form.get('controlName').markAsDirty()
You can also achieve this with the form directive as per shown here
For the submitted part, add the template reference to your form along the rest you have:
<form .... #formDir="ngForm">
Then you can just add formDir.submitted to your if statements, for the blur functionality you can just check that the field has been touched. So for your if statement, I would assign the actual form control to a variable, so that we can shorten the code, this is of course not necessary, but for readability I would do that and for example use a variable for first_name after building the form:
this.firstNameCtrl = this.addNewCustomerForm.get('first_name');
Then in your template you can do the following to achieve what you want:
<small *ngIf="firstNameCtrl.hasError('required') &&
(formDir.submitted || firstNameCtrl.touched) ">...</small>
I have done a small Web App in Angular 4 and I'm now trying to test it.
Here is what I would like to test :
<form class="navbar-form navbar-left" (ngSubmit)="onSubmit(f)" #f="ngForm">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search" ngModel name="name" pattern=".{2,}" required #name="ngModel">
</div>
<button type="submit" class="btn btn-default" [disabled]="!f.valid">
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
</button>
<span class="help-block help" *ngIf="!name.valid && name.touched ">Please enter at least two characters</span>
</form>
At first, I would just like to test if the form is really invalid (and then I cannot click on the submit button) if thye word entered in the input is less than 2 characters.
Here is the test code I have written
beforeEach(() => {
fixture = TestBed.createComponent(NavbarComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should disable submit if word<2',()=>{
const compiled = fixture.nativeElement;
const input = fixture.debugElement.query(By.css('input'));
input.nativeElement.value='b';
input.nativeElement.dispatchEvent(new Event('input'));
fixture.detectChanges();
//console.log(compiled.querySelector('input').textContent);
//console.log(compiled.querySelector('.ng-valid'));
expect(compiled.querySelector('.ng-valid')).toBe(null);
});
The textContent of the input is modified properly but the form is still valid. However, when I use the webapplication, I can't submit the form is the word is less than two characters.
I feel like the word in the input doesn't really "reach" the form in the test. I've tried a lot of different things so any help would be great !
I am new to Angular 2.
I have created a simple template which has two text field, I want to required field validate those two fields.
Login Form
<form #loginForm="ngForm" (ngSubmit)="onSubmit(loginForm)" novalidate>
<div class="container">
<div class="form-group">
ooooo <label><b>Username</b></label>
<input type="text" placeholder="Enter Username" name="uname" required [(ngModel)]="UserData.uname" #uname="ngModel">
<div *ngIf="loginForm.invalid" class="alert alert-danger">
<div [hidden]="!uname.errors.required"> Name is required </div>
</div>
</div>
<div class="form-group">
<label><b>Password</b></label>
<input type="password" placeholder="Enter Password" name="pwd" required [(ngModel)]="UserData.pwd" #pwd="ngModel">
<div *ngIf="UserData.pwd.errors && (UserData.pwd.dirty || UserData.pwd.touched)" class="alert alert-danger">
<div [hidden]="!UserData.pwd.errors.required">Password is required </div>
</div>
<button type="submit" >Login</button>
</div>
</div>
</form>
My Component
import { Component } from "#angular/core"
import { User } from "./UserModel"
#Component({
selector: 'my-login',
templateUrl:"app/Login/login.html"
})
export class LoginComponent
{
//alert: any("hello");
UserData: User = new User("", "");
submitted = false;
onSubmit(form: any) {
alert("dfsdfsd" + form);
if (!form.invalid) {
alert(this.UserData.uname);
alert(this.UserData.pwd);
this.submitted = true;
}
}
}
What i want to implement is-
When the form loads no validation message should appear?
When user clicks on the submit button then the required message should appear?
In both the textbox i have applied different type of checks to show the message that is inconsistent? so there should be a consistent way to solve this.
Many thanks for the help.
Maybe make use of the submitted variable, and use that in template, to not show message, until submitted is true, which we set it as in the submit function.
Also you wouldn't really need the two-way-binding here, since the object your form produces is directly assignable to your UserData.
The validation messages I'd just set then simply like this, where we are targeting the username:
<div *ngIf="uname.errors?.required && submitted"> Name is required </div>
in your submit function I'd pass loginForm.value as parameter instead of just loginForm. This way you get the form object ready to be used :)
And in your function you can assign the object to your UserData variable.
onSubmit(form: any) {
this.submitted = true;
this.UserData = form;
}
If you do want to keep the two-way-binding, it's of course totally possible! :)
DEMO
I have a template based form in my Angular2 app for user registration. There, I am passing the form instance to the Submit function and I reset the from once the async call to the server is done.
Following are some important part from the form.
<form class="form-horizontal" #f="ngForm" novalidate (ngSubmit)="onSignUpFormSubmit(f.value, f.valid, newUserCreateForm, $event)" #newUserCreateForm="ngForm">
<div class="form-group">
<label class="control-label col-sm-3" for="first-name">First Name:</label>
<div class="col-sm-9">
<input type="text" class="form-control" placeholder="Your First Name" name="firstName" [(ngModel)]="_userCreateForm.firstName"
#firstName="ngModel" required>
<small [hidden]="firstName.valid || (firstName.pristine && !f.submitted)" class="text-danger">
First Name is required !
</small>
</div>
</div>
.......
.......
<div class="form-group">
<div class="col-sm-offset-3 col-sm-12">
<button type="submit" class="btn btn-default">Submit</button>
<button type="reset" class="btn btn-link">Reset</button>
</div>
</div>
</form>
In my component file, I have written following function.
onSignUpFormSubmit(model: UserCreateForm, isValid: boolean, form: FormGroup, event:Event) {
event.preventDefault();
if (isValid) {
this._userEmail = model.email;
this._authService.signUp(this._userCreateForm).subscribe(
res => {
console.log("In component res status = "+res.status);
if(res.status == 201){
//user creation sucess, Go home or Login
console.log("res status = 201");
this._status = 201;
}else if(res.status == 409){
//there is a user for given email. conflict, Try again with a different email or reset password if you cannot remember
this._status = 409;
}else{
//some thing has gone wrong, pls try again
this._serverError = true;
console.log("status code in server error = "+res.status);
}
form.reset();
alert("async call done");
}
);
}
}
If I submit an empty form, I get all validations working correctly. But, when I submit a valid form, Once the form submission and the async call to the server is done, I get all the fields of the form invalid again.
See the following screen captures.
I cannot understand why this is happening. If I comment out form.reset(), I do not get the issue. But form contains old data i submitted.
How can I fix this issue?
I solved this By adding these lines:
function Submit(){
....
....
// after submit to db
// reset the form
this.userForm.reset();
// reset the errors of all the controls
for (let name in this.userForm.controls) {
this.userForm.controls[name].setErrors(null);
}
}
You can just initialize a new model to the property the form is bound to and set submitted = false like:
public onSignUpFormSubmit() {
...
this.submitted = false;
this._userCreateForm = new UserCreateForm();
}
You need to change the button type submit to button as following.
<div class="form-group">
<div class="col-sm-offset-3 col-sm-12">
<button type="button" class="btn btn-default">Submit</button>
<button type="reset" class="btn btn-link">Reset</button>
</div>
</div>
Reseting the form in simple javascript is the solution for now.
var form : HTMLFormElement =
<HTMLFormElement>document.getElementById('id');
form.reset();
this is how finally I had achieved this. I am using Angular5.
I have created a form group named ="firstFormGrop".
If you are not using form groups you can name the form as follow:
<form #myNgForm="ngForm">
In the html doc:
<form [formGroup]="firstFormGroup">
<button mat-button (click)='$event.preventDefault();this.clearForm();'>
<span class="font-medium">Create New</span>
</button>
</form>
In the .ts file:
this.model = new MyModel();
this.firstFormGroup.reset();
if you where using #myNgForm="ngForm then use instead:
myNgForm.reset();
// or this.myNgForm.reset()
This is a very common issue that after clicking the reset button we created the validators are not reset to its initial state, and it looks ugly.
To avoid that we have two options,the button is outside the form, or we prevent the submission when the button is tagged inside the form.
To prevent this default behaviour we need to call $event.preventDefault() before whatever method we are choosing to clear the form.
$event.preventDefault() is the key point.
The solution:
TEMPLATE:
<form
action=""
[formGroup]="representativeForm"
(submit)="register(myform)"
#myform="ngForm"
>
*ngIf="registrationForm.get('companyName').errors?.required && myform.submitted"
COMPONENT:
register(form) {
form.submitted = false;
}
Try changing the button type from "submit" to "button", e.g. :
<button type="button">Submit</button>
And move the submit method to click event of the button. Worked for me!