Setting $invalid and $error doesn't invalidate the form - angularjs

I have a form which I'm in the process of changing my phone fields from using a regex to the intl-tel-input module. I'm running into problems & confusion in checking for valid #s.
I have a form with several of these fields...
<div class="row">
<div class="col-xs-2">
<label for="cellPhone"
translate>CONTACT.CELL</label>
</div>
<div class="col-xs-6"
ng-class="{'has-error': !cellPhoneFocus && forms.contactForm.cellPhone.$invalid && forms.contactForm.cellPhone.$touched }">
<input type="text" class="form-control intlPhoneInput"
id="cellPhone" name="cellPhone"
ng-model="contact.cellPhone.display"
ng-focus="cellPhoneFocus = true"
ng-blur="cellPhoneFocus = false; validatePhone($event)">
<div ng-messages="forms.contactForm.cellPhone.$error"
ng-show="!cellPhoneFocus && forms.contactForm.cellPhone.$touched"
class="errorMessages">
<p ng-message="pattern" translate>
CRUD.VALID_PHONE</p>
</div>
</div>
and the submit...
<button type="submit" class="btn btn-primary" ng-disabled="forms.contactForm.$invalid" id="saveContactLink" translate>CRUD.SAVE</button>
Then in my controller (Typescript)...
//In Constructor
$scope.validatePhone = this.validatePhone.bind(this);
//Outside constructor
private validatePhone(eventObject: any) {
let thePhoneField = $('#' + eventObject.target.id);
let phoneIsValid = thePhoneField.intlTelInput("isValidNumber");
this.$scope.forms.contactForm[eventObject.target.id].$invalid = !phoneIsValid;
this.$scope.forms.contactForm[eventObject.target.id].$error = {"pattern": !phoneIsValid};
}
This properly sets my has-error class and error message, but it doesn't set the FORM to invalid. I've tried $setValidity...
this.$scope.forms.contactForm[eventObject.target.id].$setValidity('pattern', !phoneIsValid);
...but it doesn't seem to do anything at all.
How do I set the field to invalid, show the correct ng-message(if there's more than one), and make sure the form $errors gets updated so the submit is disabled?

Turns out $setValidity WAS working, but having setValidity along with .$invalid and $error caused some crossed wires. Commenting out the last two enabled/disabled my submit button correctly when invalidating a field.

You should just be able to set the form to invalid like so:
forms.contactForm.$invalid = true

Related

add new angularJs event to a button on input value change using controller in angularJs

I m trying to add angularJs event to a button if value of input field changes. But i cannot find a solution how can i do it. I know how to detect change but do not know how to add a new event using controller.
Let me illustrate by example:
<form name="addNewCourse">
<input ng-model="courseNameEdit" ng-value="courseName" ng-pattern="regex" ng-trim="false" name="addNewCourseField" ng-minlength="5" ng-maxlength="60" required>
<div ng-messages="addNewCourse.addNewCourseField.$error" style="text-align: left !important; color:red;">
<div ng-message="required">This field is required*</div>
<div ng-message="pattern">Must be only digits or numbers</div>
<div ng-message="maxlength">Must not exceed 60 characters</div>
<div ng-message="minlength">Must not be smaller than 5 characters</div>
</div>
<button class="btn btn-primary" ng-click="saveCourseNameFunc(courseNameEdit)">Save</button>
</form>
what i want is to add ng-disabled="addNewCourse.$invalid" into the button if value change using controller. Thanks in Advance.
If I'm not wrong here, You are about to validate your form while field value changes via the controller. Try below solution and let me know if this will not work for you.
FORMOBJECT.$setSubmitted();
You can also try triggering change event of that field via controller like:
angular.element('#INPUT_ID').trigger('change');
Hope you will get the solution from one of the given above.
How about using ng-change and a boolean in your ng-disabled expression activate the disability simply.
<form name="addNewCourse">
<input ng-change="changed()" ng-disabled="addNewCourse.$invalid && activeDisable" ng-model="courseNameEdit" ng-value="courseName" ng-pattern="regex" ng-trim="false" name="addNewCourseField" ng-minlength="5" ng-maxlength="60" required>
<div ng-messages="addNewCourse.addNewCourseField.$error" style="text-align: left !important; color:red;">
<div ng-message="required">This field is required*</div>
<div ng-message="pattern">Must be only digits or numbers</div>
<div ng-message="maxlength">Must not exceed 60 characters</div>
<div ng-message="minlength">Must not be smaller than 5 characters</div>
</div>
<button class="btn btn-primary" ng-click="saveCourseNameFunc(courseNameEdit)">Save</button>
</form>
and your controller must contain something like this:
$scope.activeDisable = false;
$scope.change = function(){
$scope.activeDisable = true;
}

How to reset a form in AngularJS

I'm working in AngularJS with a very simple form that only has a textarea input and a submit button. The textarea is a required field. Everything works... until I've submitted the form. When I remove the value from the model after submitting the form, this triggers my validation errors. If I don't set the value to null or an empty string, the textarea retains the entered value, which is not what I want.
<form name="notesForm" class="form-horizontal" ng-submit="vm.addNotesForm(notesForm)" novalidate>
<div control-validator="" validator-condition="vm.hasTriedToSubmit">
<div class="col-sm-10">
<!-- hidden field workaround for validation for textarea -->
<input type="hidden" id="hiddenNewNote" name="hiddenNewNote" required ng-model="vm.newNote.note" />
<textarea id="newNote"
name="newNote"
class="form-control"
placeholder="Note"
ng-disabled="vm.isWorking"
ng-model="vm.newNote.note"
rows="3"></textarea>
<control-validator-message>Note is required.</control-validator-message>
</div>
<div class="col-sm-2">
<button class="btn btn-success" type="submit" ng-disabled="vm.isWorking">
<i class="fa fa-save"></i>
Add Note
<i class="fa fa-circle-o-notch fa-spin" ng-show="vm.isWorking"></i>
</button>
</div>
</div>
Since validation only works for input fields, the hidden field is necessary.
this.notesService.addNote(this.newNote).then(() => {
this.notificationService.success('Successfully added new AR Note');
this.isWorking = false;
this.newNote.note = null; // <- This is where it goes sideways.
this.refreshDataTable();
}, errorMessage => {
this.notificationService.error(errorMessage);
this.isWorking = false;
});
I've tried all sorts of solutions. I used the FormController to set the form to pristine and untouched - no luck. I saw a proposed solution where the controls on the form were programmatically set to 'undefined'. Still no luck. Either the form submits and my value stays there in my textarea, or I set the note to null/empty string, and the validation errors get set off as if I've tried to post without a value in the textarea. As a total hack I even tried using jQuery to set the value of the textarea to an empty string, while keeping the model state undisturbed. While this did appear to work, since the value is still stored in the model, if a user clicks the add button again, it reposts. Not what I need. I'd think this would be a cinch, but after an hour of looking for an answer online, I've come up with nothing that works.

AngularJS - How to set validity true after change the field

I've followed this answer to run custom server side validation for unique email constraint.
This is my submit function on controller:
function submit(form){
CompanyUser.save(vm.model)
.success(function(data) {
vm.closeModal();
toastSucess(data);
})
.error(function(data) {
if(data.code == 'error_duplicated_email')
form['email'].$setValidity("uniqueEmail", false);
});
}
and here my email piece of HTML code:
<form name="form" novalidate ng-click="form.$valid && vm.submit(form)">
<div class="form-group" ng-class="{ 'has-error': form.$submitted && form.email.$error.uniqueEmail }">
<label>E-mail</label>
<input type="email" class="form-control" name="email" ng-model="vm.model.email" required>
<span ng-show="form.$submitted && form.email.$error.uniqueEmail" class="help-block">Duplicated e-mail</span>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-white" ng-click="vm.closeModal()">Cancel</button>
<button type="submit" class="btn btn-primary">Save</button>
</div>
</form>
And works fine once that server returns the error. But, then I change the email and try to submit, but I cannot do it anymore. I think that is because I've set the validity to false. So how can I set to true to try to submit the form again?
You can try to use the $setPristine(); method.
From angular documentation:
$setPristine(); Sets the form to its pristine state.
This method sets the form's $pristine state to true, the $dirty state
to false, removes the ng-dirty class and adds the ng-pristine class.
Additionally, it sets the $submitted state to false.
This method will also propagate to all the controls contained in this
form.
Setting a form back to a pristine state is often useful when we want
to 'reuse' a form after saving or resetting it.
Here is the solution from #code90:
I needed to add a ng-change="form.$valid=true" to the <input type="email"..
and it works fine!

Error message does not hide after angular form validation

This is my form my HTML
<form id = "myform" name="myform" ng-submit="saveForm()" novalidate >
<div class="input-group">
<span class="input-group-addon"> <img src="/icon.png" alt=""/> </span>
<input type="text" class="form-control" id="username" name="username" ng-model="username" placeholder="Username" autofocus required>
</div>
<span ng-show="formInvalid">Please enter username</span>
<button type="submit" class="btn btn-default" id="saveBtn"> Save </button>
</form>
And inside the controller I have
$scope.formInvalid = false;
$scope.saveForm = function(){
if($scope.myform.username.$invalid){
$scope.formInvalid = true;
}
if($scope.myform.$valid){
//....save it....
At first the form has no error message, if I hit "Save" the "Please enter username" appears, so far, all good.
But if I click on the form field to type a username, the error message does not go away. Even if I finish typing and click somewhere else, the error message still does not go away.
I also try
if(!$scope.myform.username.$valid){
$scope.formInvalid = true;
}
and I also try together
if(!$scope.myform.username.$valid){
$scope.formInvalid = true;
}
if($scope.myform.username.$valid){
$scope.formInvalid = false;
}
and the problem is still there. How can I debug? How do I fix this?
Thanks
You don't have to introduce and maintain a new variable ($scope.formInvalid) for managing the state of your form. Angular maintains the valid / invalid state of the form for you.
As your form is named myform, just show the message about the username based on the value of myform.username.$invalid, and save the form only if myform.$valid is true:
HTML
<span ng-show="myform.username.$invalid">Please enter username</span>
JS
$scope.saveForm = function () {
if ($scope.myform.$valid) {
// save the form
}
};
See fiddle
you can try a watch event,
$scope.$watch('myform.$valid', function(n, o) {
if(n) {
$scope.formInvalid = false;
} else {
$scope.formInvalid = true;
}
});
But i might even be a better idea, if you start using validators.
you do not trigger a change to form invalid property anywhere, I suggest you solve this issue with angulars built in validators and ng-messages module, which will listen to changes on you're form inputs and notify when the inputs are valid or invalid and notify the warning text.
Another approach you can take is use the ng-change directive on the inputs you want to listen to changes in and trigger and update on the form invalid property according to the inputs validity.
example : (taken from the official angular website )
<form name="myForm">
<label>
Enter your name:
<input type="text"
name="myName"
ng-model="name"
ng-minlength="5"
ng-maxlength="20"
required />
</label>
<pre>myForm.myName.$error = {{ myForm.myName.$error | json }}</pre>
<div ng-messages="myForm.myName.$error" style="color:maroon" role="alert">
<div ng-message="required">You did not enter a field</div>
<div ng-message="minlength">Your field is too short</div>
<div ng-message="maxlength">Your field is too long</div>
</div>
</form>
i think this is the most elegant way to do it.

AngularJS not validating email field in form

I have the html below where I have a form that I want to submit to the AngularJS Controller.
<div class="newsletter color-1" id="subscribe" data-ng-controller="RegisterController">
<form name="registerForm">
<div class="col-md-6">
<input type="email" placeholder="your#e-mail.com" data-ng-model="userEmail" required class="subscribe">
</div>
<div class="col-md-2">
<button data-ng-click="register()" class="btn btn-primary pull-right btn-block">Subsbcribe</button>
</div>
</form>
</div>
And the controller is below
app.controller('RegisterController', function ($scope,dataFactory) {
$scope.users = dataFactory.getUsers();
$scope.register = function () {
var userEmail = $scope.userEmail;
dataFactory.insertUser(userEmail);
$scope.userEmail = null;
$scope.ThankYou = "Thank You!";
}
});
The problem is that no validation is taking place when I click the button. It is always routed to the controller although I do not supply a correct email. So every time I click the button I get the {{ThankYou}} variable displayed. Maybe I do not understand something.
AngularJS does not disable enable any functionality for form validations. What is does is, it makes the state of the form and its control in terms of validation available on the current scope. You are required to implement the behaviour yourself.
In your case if you need to check user email is valid your html input should have a name attribute like
<input type="email" placeholder="your#e-mail.com" data-ng-model="userEmail" required class="subscribe" name='userEmail'>
Then on your controller you can check
$scope.registerForm.userEmail.$invalid property.
You can use the same property to disable the button on the form using ng-disabled
<button data-ng-click="register()" class="btn btn-primary pull-right btn-block" ng-disabled='registerForm.userEmail.$invalid'>Subsbcribe</button>
Basically the registerForm object is a ngFormController and userEmail is ngModelController. Please read the developer guide for forms
You are missing some part to achieve what you want. Normally you will need to add some code to enable disable the submit button base on the state of the form i.e valid/invalid. In your case this can be done like that :
<button data-ng-click="register()" class="btn btn-primary pull-right btn-block" ng-disabled="registerForm.$invalid">Subsbcribe</button>
Notice the ng-disabled="registerForm.$invalid".
You can as well provided inline feedback to the user with something like :
<input type="email" placeholder="your#e-mail.com" data-ng-model="userEmail" required="" class="subscribe" name="userName"/>
<span ng-show="registerForm.userName.$error.required">Please enter a name</span>
Or with CSS like that :
input.ng-invalid-required {
background-color: #FA787E;
}
You have a working plunker here

Resources