I am trying to validate template driven form in Angular without two way databinding. I have done validation using [(ngModel)] but when i try to validate form without MODEL i get following error
Cannot read property 'invalid' of undefined
This is my HTML code.
<div class="jumbotron">
<div class="container">
<div class="row">
<div class="col-md-6 offset-md-3">
<h3>Angular 6 Template-Driven Form Validation</h3>
<form name="form" (ngSubmit)="onSubmit(f.value)" #f="ngForm" novalidate>
<div class="form-group">
<label for="username">Username:</label>
<input type="text"
class="form-control"
name="username"
#userName
required
minlength="8"/>
<div *ngIf="f.form.controls.username.invalid && f.form.controls.username.touched" class="invalid-feedback">
<div *ngIf="f.form.controls.username.errors.required" class="alert alert-danger">Username is required</div>
<div *ngIf="f.form.controls.username.minlength" class="alert alert-danger">length should b 8 character</div>
</div>
</div>
<button class="btn btn-primary" >Register</button>
</form>
</div>
</div>
</div>
</div>
It also not sending data to component when i click button.
this is component TS file .
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-template-driven-form',
templateUrl: './template-driven-form.component.html',
styleUrls: ['./template-driven-form.component.css']
})
export class TemplateDrivenFormComponent {
// model: any = {};
onSubmit(f) {
// alert('SUCCESS!! :-)\n\n' + f);
console.log(f);
}
}
Just replace:
f.form.controls.username.invalid
with
username.invalid
but its mandatory to use ngModel
so your HTML control:
<input type="text" ngModel class="form-control" name="username" #username="ngModel" required minlength="8"/>
It's not working because it shouldn't.
As you can see, inputs that aren't bound with ngModel aren't part of your form.
So simply use ngModel and you should be good to go.
Related
I have a template form, which I wrote from guides and they don't really work though.
I have several of models:
export class User {
constructor(public userId?: UserId,
public firstName?: String,
public lastName?: String,
public address?: Address) {
}
}
export class Address {
constructor(
public street?: String,
public city?: String,
public zipCode?: String) {
}
}
I have component:
Component({
templateUrl: 'user.html'
})
export class MyComponent implements OnInit, OnDestroy{
user: User;
userForm: NgForm;
ngOnInit(): void {
}
And page itself:
<form novalidate #userForm="ngForm">
<div class="form-group">
<input required minlength="4" type="text"
id="firstName"
[(ngModel)]="user.firstName" name="firstName">
<small *ngIf="!firstName.valid">Not valid!</small>
</div>
<div class="form-group">
<input required ng-minlength="4" type="text"
id="lastName"
[(ngModel)]="user.lastName" name="lastName">
</div>
<div ngModelGroup="user.address">
<div class="form-group">
<input required ng-minlength="4"
type="text"
id="address-house"
[(ngModel)]="user.address.address1" name="address.address1">
</div>
<div class="form-group">
<div class="form-group">
<input required ng-minlength="4"
type="text"
id="zipCode"
[(ngModel)]="user.address.zipCode" name="address.zipCode">
</div>
<div>
<input required ng-minlength="4"
type="text"
lass="form-control input-lg"
id="city"
[(ngModel)]="user.address.city" name="address.city">
</div>
</div>
</div>
<button type="button" (click)="checkAndProceed()">Continue</button>
</div>
</form>
The only thing I want to do is to add validation - that's all. None of the guides helped. Can we do in-html validation or ts validation? It would be nice to call validation when clicking 'Continue' button and making it valid if it is so.
In this case of validation I additionally get console error:
Cannot read property 'valid' of undefined
There are lots of attributes on input elements. We have name, Id, and template reference variable. Your code is missing the template reference variable. It is the template reference variable that holds onto the reference to the element and has the valid, dirty, and other flags associated with it.
For example, change your code to include a template reference variable like this:
<div class="form-group">
<input required minlength="4" type="text"
id="firstName"
[(ngModel)]="user.firstName" name="firstName"
#firstNameVar="ngModel">
<small *ngIf="!firstNameVar.valid">Not valid!</small>
</div>
Notice the #firstNameVar. That is the template reference variable. It can be named the same thing as your Id and name attributes. I just named it something different so it could be readily distinguished between the other two attributes.
Notice also that the *ngIf is then changed to use firstNameVar.valid
For more information on template reference variables, see this: https://angular.io/guide/template-syntax#ref-vars
I want to validate a text input in form, so the submit of the form could not be done until the input match a regular expression. But when I type a wrong field value and I clik submit the form is submitted but the input value is not sent to the server. I want the same behaviour as with HTML5 required Attribute. This is my code:
<div class="row">
<label class="col-sm-2 label-on-left">APN</label>
<div class="col-sm-7">
<div class="form-group label-floating">
<label class="control-label"></label>
<input class="form-control" type="text" name="apn" ng-model="Configure3gCtrl.configure3g.apn" ng-pattern="/^[a-zA-Z0-9-.]*$/" required/>
</div>
</div>
</div>
As i said in the comment [value not sent because when you pass the input with incorrect pattern the ng-model is undefined].
But we can use the form validation here as sample if our ng-model are invalid the form will disabled.
var app = angular.module("app", []);
app.controller("ctrl", ["$scope", "$filter", function($scope, $filter) {
$scope.submit = function() {
console.log($scope.object)
}
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<form name="form">
<label class="col-sm-2 label-on-left">APN</label>
<input type="text" name="apn" ng-model="object.apn" ng-pattern="/^[a-zA-Z0-9-.]*$/" required />
<button ng-click="submit()" ng-disabled="form.$invalid">submit</button>
</form>
</div>
Ideally, you should not send the invalid value to server, So you should disable\hide your submit button, but if you really require sending the invalid value as well to server, then from angularjs 1.3+ you have ng-model-options (Read Doc) directive which can help you.
Simply mark your text type input as ng-model-options="{allowInvalid: true }", It will persist the invalid values as well.
See Demo:
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', function MyCtrl($scope) {
$scope.submitt = function() {
alert($scope.Configure3gCtrl.configure3g.apn);
}
$scope.Configure3gCtrl = {
configure3g: {
apn: ""
}
}
});
<script src="https://code.angularjs.org/1.3.1/angular.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<form name="frm" ng-submit="submitt()" class="row">
<label class="col-sm-2 label-on-left">APN</label>
<div class="col-sm-7">
<div class="form-group label-floating">
<label class="control-label"></label>
<input class="form-control" type="text" name="apn"
ng-model="Configure3gCtrl.configure3g.apn"
ng-model-options="{allowInvalid: true }"
ng-pattern="/^[a-zA-Z0-9-.]*$/" required/>
</div>
</div>
<input type="submit" value="submit" type="submit" />
</form>
</div>
also, Test with removing ng-model-options="{allowInvalid: '$inherit' }" from above code snippet then ng-model will be undefined, because it is invalid.
Using the aurelia-validator plugin, even though the code for form submission and validation works properly, all properties are properly updated, the UI doesn't change, like I don't get a red window around properties which are not correct, nor the statement of what is wrong with given form property.
It's not connected to my CSS, I tried removing whole my css and still it doesn't work. Any idea what's wrong here? Missing something?
contact.js
import {inject} from 'aurelia-framework';
import {Validation} from 'aurelia-validation';
#inject(Validation)
export class Contact{
firstName = 'John';
lastName = '';
company = '';
subject = 'product question';
email = '';
messageText = 'test';
constructor(validation){
this.validation = validation.on(this)
.ensure("firstName")
.isNotEmpty()
.ensure("lastName")
.isNotEmpty()
.ensure("email")
.isNotEmpty()
.isEmail();
}
contact(){
this.validation.validate()
.then(() => {
console.log("works");
})
.catch(() => {
console.log("error");
});
}
}
contact.html
<template>
<div class="row contact-container">
<div class="col-md-4 col-md-offset-3">
<form role="form" validate.bind="validation" submit.delegate="contact()">
<label>First Name</label>
<input type="text" value.bind="firstName" class="form-control" >
<label>Last name</label>
<input type="text" value.bind="lastName" class="form-control">
<label>Company</label>
<input type="text" value.bind="company" class="form-control">
<label>Email</label>
<input type="text" value.bind="email" class="form-control">
<label >Subject</label>
<select value.bind="subject" class="form-control">
<option value="product question">Product Question</option>
<option value="cooperation">Cooperation</option>
<option value="Other">Other</option>
</select>
<label for="message">Message</label>
<textarea rows="5" id="message" value.bind="messageText" class="form-control"></textarea>
<br></br>
<input type="submit" class="form-control">
</form>
</div>
</div>
</template>
I guess the problem is related to the fact that Your markup doesn't match ViewStrategy You are using.
I suspect You might be using some ViewStragegy provided by Aurelia, for example https://github.com/aurelia/validation/blob/master/doc/Intro.md#configuseviewstrategyviewstrategyinstance that expects Twitter Bootstrap markup. If that is the case, You should group Your form intputs to form-groups - see the demo (http://aurelia.io/validation/#/) and source of the TWBootstrapViewStrategyBase class: https://github.com/aurelia/templating-validation/blob/master/src/strategies/twbootstrap-view-strategy.js#L11
Use form-group class, don't forget about validate on input
try smth like
<div class="form-group">
<label class="col-sm-3">Land</label>
<div class="col-sm-6">
<input class="input-small col-sm-12" type="text"
placeholder="Land"
value.bind="model.item.country" validate="country">
</div>
</div>
I have a register form that I wish to do validation on the moment a user clicks submit. This is what the HTML looks like:
<form ng-submit="RegistrationC.fireReg()" novalidate name="register">
<div class="row">
<div class="col-md-6 form-group">
<input type="text" autocomplete="off" class="form-control" placeholder="First Name" ng-model="RegistrationC.first_name" required name="first_name">
<div class="help-block" ng-messages="register.first_name.$error" ng-show="submitted && register.first_name.$error">
<p ng-message="required">This field is required.</p>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 form-group col-md-offset-3">
<button type="submit" class="btn btn-success btn-block" ng-click="submitted=true">Register Now</button>
</div>
</div>
</form>
It is showing the validation message if a username is not typed in, but it still submits. What am I missing?
EDIT 1
//init.js - RegistrationController
reg_list.fireReg = function () {
var url = 'user/register';
api.makeCall(reg_list, url)
.then(function (response) {
reg_list.response = response;
console.warn(response);
$location.path('/user/verify');
})
.catch(function (errorMessage) {
console.log("got an error in initial processing", errorMessage);
event.restoreButton();
});
};
I know there's issues in this function, I will fix them at a later stage.
Submit this form only if it is valid. <whatever_form_name>.$valid
<form ng-submit="register.$valid && RegistrationC.fireReg()" novalidate name="register">
Just add checkpoint whether form is valid or not before submitting form
Try like this
<form ng-submit="register.$valid && RegistrationC.fireReg()" novalidate name="register">
If you want to disable html5(or browser) validator, You have to remove 'required' attribute in your html code
http://www.the-art-of-web.com/html/html5-form-validation/
http://www.w3schools.com/tags/att_input_required.asp
I was trying to follow some tutorials, but couldn't figure out what to do.
I would like to add the validation, that at least one of the checkboxes (consumer/vendor) has to be true. If not true show an error message at both fields). What would be the easiest way to accomplish that?
<form role="form" name="addClientForm" ng-submit="submitForm(addClientForm.$valid)" novalidate>
<div class="form-group" ng-class="{ 'has-error' : addClientForm.title.$invalid && !addClientForm.title.$pristine }">
<label>Title</label>
<input type="text" class="form-control" placeholder="Enter a title" ng-model="client.title" required>
</div>
<div class="form-group" ng-class="{ 'has-error' : addClientForm.company.$invalid && !addClientForm.company.$pristine }">
<label>Company</label>
<input type="text" class="form-control" placeholder="Enter a company" ng-model="client.company" required>
</div>
<div class="checkbox">
<label class="i-checks">
<input type="checkbox" ng-model="client.consumer"><i></i> Consumer
</label>
</div>
<div class="checkbox">
<label class="i-checks">
<input type="checkbox" ng-model="client.vendor"><i></i> Vendor
</label>
</div>
</form>
Controller (modal controller)
angular.module('App')
.controller('ModalAddClientCtrl', function ($scope, $modalInstance) {
$scope.client = { title: '', company: '', consumer: true, vendor: false };
$scope.submitForm = function(isValid) {
};
$scope.ok = function () {
$modalInstance.close($scope.client);
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
});
To use angular form validation like you are trying to you have to set name attribute in the input fields. So, if you have a <form name='form'> with <input name='input'> only then you can use form.input.$dirty or form.input.$pristine. Combine that with ng-if like you have the rest is simple.
See this fiddle for example and try editing the values. I have implemented validation in your form. I have left out the controller, conditions and error messages could be simpler but you will get the idea.
See this related post that has an excellent answer on using form validation.