AngularJS - perform extra validation on form submit - angularjs

I've been googling for a while and can't seem to find a good answer for my specific case. I've found ways to do real-time validations but I want to combine that with some custom validations after a user clicks on "submit". I want to allow the user to still click on the submit even if it's not valid but then I'll cancel the submission in the code. Take the following code:
<form name="cashForm" id="cashForm" novalidate>
<input type="text" id="name" required /> //
<input type="number" placeholder="Tax: " required name="tax" id="tax" />
<input type="number" placeholder="Tip: " required name="tip" id="tip" />
<button ng-click="submission()" ng-disabled="paymentForm.$invalid">Submit</button>
</form>
//inside controller
this.submission = function() {
//check if tip + tax is over 20
//prevent form and show error message if not
//otherwise allow default behavior
}
So I only want the form to actually submit if the tax/tip is over 10. How do I check for this and how do I prevent the form submission if it doesn't meet the requirements? Also, would I put this logic in the controller?

It looks pretty close to what you're after to me. Just a couple of things...
Add ng-model directives to your input controls to create two-way data-bindings that you can pick up and use in your controller:
<form name="cashForm" id="cashForm" novalidate>
<input id="name" name="name" type="text" ng-model="nameValue" required />
<input id="tax" name="tax" type="number" ng-model="taxValue" placeholder="Tax: " required />
<input id="tip" name="tip" type="number" ng-model="tipValue" placeholder="Tip: " required />
<button
ng-click="submission()"
ng-disabled="paymentForm.$invalid">
Submit
</button>
Inject $scope into your controller to allow you to pick up those ng-model bindings in your controller's submission method:
function submission() {
$scope.errorMsg = "";
if ($scope.taxValue <= 10) {
$scope.errorMsg = "tax not greater than 10";
return;
}
if ($scope.tipValue <= 10) {
$scope.errorMsg = "tip not greater than 10";
return;
}
// If you reached here your post-click validation passed,
// so continue to submit the data...
}
You could then display an error message using the ng-if directive with a css class that highlights the error message:
<div ng-if="!!errorMessage" class="text-danger">
{{ errorMessage }}
</div>
Finally, once you've cracked using $scope in your controller you might want to read about the perceived evils of using $scope and consider switching to controller-as syntax instead. Check out John Papa's Blog Post AngularJS's Controller As and the vm Variable

Related

How to reset validation after submitting a form in AngularJS?

I have one input field:
<input type="text" name="title" ng-model="genreData.title" class="form-control"
ng-class="{'error': addGenreForm.title.$invalid && !addGenreForm.title.$pristine}"
placeholder="Genre name" ng-minlength="minlength" required autofocus>
When I succesfully submit form this input is got class="error" after this:
$scope.genreData = {};
How can I fix it?
You've got to inject the form in the ng-submit function and then call the form's controller built in function $setPristine().
e.g.
View:
<form name="myForm" ng-submit="submitForm(myForm)">
<!--Input Fields-->
</form>
Controller:
$scope.submitForm = function(form) {
//Do what ever I have to do
//Then reset form
form.$setPristine();
}
I think setting
$scope.addGenreForm.$setPristine() and $scope.addGenreForm.$setUntouched
can work after submitting your form
Please share some plunker so I can help more if you still have any issues

Angular: Disable button on click after required fields are filled in the form

I need to disable the submit button after clicking on the button to prevent multiple submissions but before the it has to ensure that the required fields are filled.
I tried
<body ng-app="ngToggle">
<div ng-controller="AppCtrl">
<form name="newUserForm">
<input type="text" required>
<input type="text" required>
<input type="text">
<button ng-click="disableClick()" ng-disabled="isDisabled"
ng-model="isDisabled">Disable ng-click</button>
</form>
</div>
</body>
angular.module('ngToggle', [])
.controller('AppCtrl',['$scope', function($scope){
$scope.isDisabled = false;
$scope.disableClick = function() {
alert("Clicked!");
$scope.isDisabled = true;
return false;
}
}]);
but this will only disable the button without any validation
Ok, I get what you mean/want so I'll try to help and come up with some code - which is obviously missing but if it wasn't missing the necessary code, you'd have the solution :)
First, you'll have to properly write your form:
<form name="newUserForm" ng-submit="disableClick(newUserForm.$valid)" novalidate>
<input type="text" name="input1" ng-model="form.input1" required>
<input type="text" name="input2" ng-model="form.input2" required>
<input type="text" name="input3" ng-model="form.input3"> //not required
<button type="submit" ng-disabled="isDisabled">Disable ng-click</button>
</form>
so what we've got here, which you're missing:
You did name your form, but you're missing a submit, in the form as ng-submit or the button with type="submit", which will submit the form and that's when the validation happens
In order for Angular to validate your inputs, they need to have ng-model, otherwise it will not validate (HTML5 validation would, but read on)
I've added novalidate so we tell the browser "Hey, we need this validated but not by you, so do nothing", and Angular takes over
And last but not least, Angular adds a couple of properties to the form (see more here: Angular form Docs), $valid being one of them, which is set to true when all validated inputs are valid.
So this sums up the changes you needed to do to your form.
As for the Javascript part, there is just one small change:
$scope.disableClick = function(valid) {
if(valid && !$scope.isDisabled) {
$scope.isDisabled = true;
}
return false;
}
I guess the change is obvious, but I'll explain anyway - check that newUserForm.$valid (boolean) and if it's true (meaning form has passed validation) disable this button.
Of course, you'll have to add checks not to run the code on any type of submits and not just disabling the button (which can easily be re-enabled via Dev Tools), so that's why I added !$scope.isDisabled to the if statement.
Hope this answers your question :)
P.S. Here's a running demo in Plunker

Angular - Cannot read property '$invalid' of undefined

I am creating a login page using angular and typescript. When the submit button is clicked, I would like the login function in the controller to fire, but if the form is invalid then it just returns.
This is my first time using typescript, so every time I try to put in the if statement to check if the form is invalid it throws the error Cannot read property '$invalid' of undefined.
Here is the html:
<form class="login-form" name="loginForm" ng-submit="vm.login()" novalidate>
<input type="email" name="email" placeholder="Email" required ng-model="vm.email" ng-class="{true: 'input-error'}[submitted && loginForm.email.$invalid]"/>
<input type="password" name="password" placeholder="Password" required ng-model="vm.password" ng-class="{true: 'input-error'}[submitted && loginForm.password.$invalid]"/>
<input type="submit" id="submit" ng-click="submitted=true"/>
</form>
And here is the compiled javascript:
var LoginModule;
(function (LoginModule) {
var LoginController = (function () {
function LoginController() {
}
LoginController.prototype.login = function () {
if(this.loginForm.$invalid) {
return;
}
console.log("Login was clicked, email is " + this.email + " and password is " + this.password);
};
return LoginController;
})();
LoginModule.LoginController = LoginController;
})(LoginModule || (LoginModule = {}));
angular.module('loginModule', []).controller('LoginController', LoginModule.LoginController);
It looks like the common issue with this was that people were not specifying the form name, but that is not the case here. Does anyone know why I could be getting this error?
You need the controller alias in the form name
<form name="vm.loginForm" ng-submit="vm.login()" novalidate>
While #charlietfl's answer is correct for the OP's question, this error can also be thrown if you've missed the ng-model property on an input control and are using the ui.bootstrap.showErrors $scope.$broadcast('show-errors-check-validity') method.
As per the documentation (my emphasis):
.. an input control that has the ngModel directive holds an instance of NgModelController. Such a control instance can be published as a property of the form instance using the name attribute on the input control. The name attribute specifies the name of the property on the form instance.

How to use Angular input fields email validation inside controller?

I'm trying to validate a variable as email inside Angular controller.
var valid = $filter('email')($scope.email);
The email filter doesn't exists, generates "unknown provider error". What's the correct way to access email validation from inside the controller?
Thanks.
Later edit: don't put me to create a custom filter, it must be a way using angular validation.
You can create a hidden input type email:
<input type="email" hidden id="emailValidator" required ng-model="x" />
Then in js set the value to that input and check validity:
var validator = $('#emailValidator')[0];
validator.value = "someemail#tovalidate.com";
return validator.checkValidity();
Also this documentation could be helpful: https://docs.angularjs.org/guide/forms
You could use form and prevent form submission by adding ng-disabled to the submit button:
<form name="form">
<input type="email" ng-model="email" name="email" required/>
<button type="submit"
ng-disabled="form.$invalid">Submit</button>
</form>
{{form.email.$valid}}
As the point of validation is to prevent submission and show error messages. I think it's enough to do it there instead of controllers where you handle your business logic.
DEMO
You can write your own filter:
angular.module(/**some module description here**/).
filter('email',function(){
var validateEmail = function(email) {
var re = /^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(email);
}
return function(input){
return validateEmail(input);
};
});
Regular expression is borrowed from here

empty form field is still being submitted when using angular form validation

The validation is being highlighted correctly, but when I click submit button, even with empty form field, the form is still being submitted (and nick value is undefined)
I tried adding novalidate to the form -- but that didn't help.
<form class="nick" ng-submit="joinChat()">
<input type="text" required name="nick" ng-model="nick" ng-minlength="2" ng-maxlength="10">
<button>Join</button>
</form>
I'm trying to follow this guide here:
http://www.ng-newsletter.com/posts/validations.html
The joinChat() function doesn't do any validation itself. As its my understanding this shouldn't be necessary when using Angular form validation.
$scope.joinChat = function(){
socket.emit('chat:join', { nick: $scope.nick });
};
Invalid input does not prevent angular form submission, instead try this:
<form class="nick" novalidate ng-submit="joinChat()" name="myform">
<input type="text" ng-required="true" name="nick" ng-model="nick" ng-minlength="2" ng-maxlength="10">
<button ng-disabled="myform.$invalid">Join</button>
</form>
Fiddle

Resources