How to reset a form in AngularJS - 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.

Related

AngularJS - validation not based on form element

Is there a way to inject some validation - custom or otherwise - that isn't tied to a form element? Like - validate that some condition is met, but have it work with standard AngularJS validation?
Update:
Here's what I'm trying to accomplish:
I have a form contains a list of sections. Each section is controlled by a checkbox, and the section will display (via an ng-if) when the checkbox is checked.
Within each section, there's an opportunity for an item to be selected via a popup modal that is activated by a button click. Until an item is selected for that section, the form needs to be invalid. Once an item is selected for each selection that is checked, then the form needs to be valid.
I have a button at the bottom of the form with an ng-disabled="frm.$invalid". I want that to stay disabled until each section that has been checked contains an item that was selected via the modal.
Update 2:
Here's some example code:
<form class="form-horizontal" role="form" name="frm" novalidate>
<label>Name: </label>
<input type="text" ng-model="name" required/>
<div ng-repeat="orderItem in orderItems">
<input type="checkbox" name="items[]" ng-model="orderItem.selected"/>
<div ng-if="orderItem.selected">
... bunch of form fields
<button ng-click="openExchangeSelectionModal(orderItem)">Select Item</button>
<div ng-show="orderItem.exchange_item">
Selected Item: {{orderItem.exchange_item.name}} - ${{orderItem.exchange_item.price | number: 2}}
</div>
</div>
</div>
<button ng-disabled="frm.$invalid" ng-click="submitOrder">Submit</button>
</form>
Checking if the form is valid won't help you in this case since there is no required input that's not being filled.
What I would recommend is that the disable button would call a function that makes some logic about the number of check boxes expanded and the number of selected items and returns the buttons state (true for active otherwise false)
Let's take the example code you put up:
//some html tags...
<button ng-disabled="checkValid()" ng-click="submitOrder">Submit</button>
</form>
Notice that I changed the frm.$invalid to checkValid function, which is a function that is defined on your controller and can perform any logic you want to determine rather show your submit button or not.

Angular not validating form select

I'm new to angular so bear with me. I have a form with a dropdown, textbox and a button. The user has to select an option from the dropbox and enter a value in the textbox before the form becomes valid.
<form name='personDataSourceForm' novalidate ng-submit='personDataSourceForm.$valid && PersonCtrl.SaveDataItem()'>
<span>Invalid: {{personDataSourceForm.$invalid}}</span><br />
<span>valid: {{personDataSourceForm.$valid}}</span>
<div class="input-group">
<div class="input-group-addon">
<select class="form-control input-sm" required ng-model='PersonCtrl.sp.person.newItem.dataType' ng-options='opt as opt.text group by opt.dataType for opt in PersonCtrl.DataItemTypes'>
<option value="" disabled selected>Choose...</option>
</select>
</div>
<input type="text" class="form-control input-sm" ng-model='PersonCtrl.sp.person.newItem.value' required>
<div class="input-group-btn">
<button class="btn btn-default btn-sm" ng-class="{ 'btn-success' : PersonCtrl.sp.person.newItem.dataType.dataType && PersonCtrl.sp.person.newItem.value }" type="submit">Save</button>
<button class="btn btn-link btn-sm" type="button" ng-click="PersonCtrl.StopAddItem()">Cancel</button></div>
</div>
</form>
I quickly added 2 spans to show the validation state. When both are empty the form shows invalid which makes sense.
As soon as I type in a value in the textbox then suddenly the form is valid even though the dropdown still hasn't been changed.
Why is my dropdown not getting validated? I've even tried this solution AngularJS Dropdown required validation
My initial thought is that you already have that default value selected:
<option value="" selected>Choose...</option>
so it does technically have a value of "", which is fulfilling the required.
I think you will need to look at PersonCtrl.sp.person.newItem. The form becomes valid when both the dataType and value get solid. My guess is the item always has its dataType solid and valid so when the new value is entered the whole form becomes valid.
Why don't your select ad input have a name attribute? The name attribute is necessary for form validations to work properly.
I think form creates a map of name->validity for each input component and it could be that you have omitted it they both (select and input) map to the same validity object. If this is the case, then anyone becomes valid, effectively makes the status of the other one valid as well and hence they are both valid the form becomes valid.
Please add separate names for them and see if the problem is resolved. My opinion above is a strong guess and I have not dived into Angular code to check ng-form's behaviour.

Display validation messages when a button is clicked

I think what I want to achieve is quite simple. Let's have a form with a required field, a select for instance (I've also tried it with an input and it's exactly the same situation anyway).
I want to display the ng-messages only when a button is clicked. If the form field was touched before clicking the button, it works fine. But I cannot do it if the form field is $untouched.
I've solved it setting programatically $touched to the form field, but I'm wondering if there is any way to solve it without this uggly 'hack'.
// Any way to avoid this line??
$scope.myForm.favoriteColor.$setTouched();
//
Code for reference:
HTML:
<md-input-container>
<label>Favorite Color</label>
<md-select name="favoriteColor" ng-model="favoriteColor" required>
<md-option value="red">Red</md-option>
<md-option value="blue">Blue</md-option>
</md-select>
<div class="errors" ng-messages="myForm.favoriteColor.$error" ng-show="validateWithHack">
<div ng-message="required">Required</div>
</div>
</md-input-container>
JS:
$scope.validateWithHack = function() {
if ($scope.myForm.$valid) {
alert('Form is valid.');
} else {
// Any way to avoid this line??
$scope.myForm.favoriteColor.$setTouched();
//
$scope.validateWithHack = true;
}
};
I'm pretty sure that this was working with previous versions of angular-material. Now I'm using the latest 1.1.1.
Here is a plunker where the
problem can be easily reproduced.
Thanks in advance.
Check the CodePen
I have added novalidate to your form and added type="submit" to your md-button
Edit 2:
The type="submit" button actually triggers a form submit and so the angular form validates itself first, What we need to do is to prevent the submit and just do the validation.
novalidate(Just to supress the HTML5 validation) to your form and added type="submit" to your md-button : This Will Validate the form and submit the form, To validate and prevent form submit add ng-click="submitMethod(<yourForm>, $event)" to the <md-button> and define method as
$scope.submitMethod(form,ev){
ev.preventDefault();
//rest of your form work say if you want to do ajax or anything you like
//check if form valid using form.$invalid
}

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

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

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