I am struggling to figure out a way to trigger these AngularJS classes on a form I am trying to automatically fill with a chrome extension I am making. The form (specifically a textbox) has to be validated/modified before it will be validated and therefore submitted.
I originally tried using javascript to set the value of the textbox using the value property. This did not validate the form. I then tried using a dispatch event to send a key to the textbox, which resulted in nothing being input into the text box. How can I validate the form without requiring human input, or is this not possible?
Clarification, I am trying to replicate this action without user input by using a chrome extension.
Reference https://www.w3schools.com/angular/angular_validation.asp
Sounds like you need to create some events to simulate whatever angular is listening for, probably change or blur. Here's an example using click from mozilla:
https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events#Triggering_built-in_events
function simulateClick() {
var event = new MouseEvent('click', {
view: window,
bubbles: true,
cancelable: true
});
var cb = document.getElementById('checkbox');
var cancelled = !cb.dispatchEvent(event);
if (cancelled) {
// A handler called preventDefault.
alert("cancelled");
} else {
// None of the handlers called preventDefault.
alert("not cancelled");
}
}
How can I validate the form without requiring human input
Get the forms controls:
var controls = $scope.tdForm.$getControls();
Trigger their validators:
controls.forEach( _ => _.$validate() );
From the Docs:
$validate();
Runs each of the registered validators (first synchronous validators and then asynchronous validators). If the validity changes to invalid, the model will be set to undefined, unless ngModelOptions.allowInvalid is true. If the validity changes to valid, it will set the model to the last available valid $modelValue, i.e. either the last parsed value or the last value set from the scope.
For more information, see
AngularJS Form Controller API Reference
AngularJS ngModelController API Reference
When you type into the form, it updates the state of its controls (touched, dirty, etc.). According to how you define your fields validators (required, minLength...) the form will be valid or not after the user input.
In your submit method you should not proceed if any form fields are not valid. See AngularJS Developer Guide — Forms or Scotch Tutorials — AngularJS Form Validation you can have more details about AngularJS validation.
As Mike mentioned, you can use ngClass conditionally (see below) to apply some style classes only if a boolean condition occurr, for example the form is not valid.
<div ng-controller="ExampleController">
<form name="form" novalidate class="css-form">
<input type="text" ng-model="user.name" name="username" ng-class="{ 'error': !isValid }"/>
<div ng-show="form.$submitted>
<span ng-show="form.username.$error">Wrong Name</span></span>
</div>
<button ng-click="submit(user)"> Submit </button>
</form>
</div>
angular.module('formExample', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.isValid = true;
$scope.submit= function(user) {
if (user.name != 'Carl') {
$scope.isValid = false;
}
};
}]);
You can always programmatically change the form states if needed. For example to set the field to pristine:
$scope.form.$setPristine();
$scope.form.$setUntouched();
$setPristine 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.
$setUntouched sets the form to its untouched state. This method can be called to remove the 'ng-touched' class and set the form controls to their untouched state (ng-untouched class).
Setting a form controls back to their untouched state is often useful when setting the form back to its pristine state.
UPDATE
Now it is clear what you are attempting to achieve. The two methods above can be used to set the form state, but if you want to validate it from code (this can be done passing the form to a service or directly in the controller for instance) then $validate() method will allow you to achieve that as mentioned by George.
Related
I have an Angular Reactive form. I subscribe to its value changes and will emit changes to parent component. Some of the controls might get disabled by the user. The problem is that values from disabled controls are missing when form valueChanges are emitted. I've set a basic example.
When the checkbox is checked and the email input is disabled, there is no form control value logged. But I'd like to get ALL form values.
Use the FormGroup's getRawValue() to include control values regardless of enable/disable state.
More information in the API documentation
this.myForm.valueChanges.subscribe(() => {
this.formValues = JSON.stringify(this.myForm.getRawValue());
});
Here is the forked example
The value from a disable input is ignored (try to submit a form with a disabled input: it won't be posted).
You can change it to 'readonly'
<input formControlName="email" [readonly]="cb.checked">
<input #cb type="checkbox" formControlName="toggleEmail">
Updated example.
this.form.valueChanges
.pipe(map((_) => this.form.getRawValue()))
.subscribe(res => {
console.log(res)
});
In an Angular 4 application, I have a template driven form with controls bound to values in my component. When the form input changes the object bound to the input changes immediately (two-way binding). When the cancel button is clicked, I want to undo the change to the bound object. This allows the user to change values then change their mind and cancel their changes.
https://plnkr.co/edit/RnnPwtHZY0qTN1H6er0z?p=preview
The plunker above has such a form with a bound field to read the hero.name
<h2>{{hero.name}} details!</h2>
An input bound to a hero object.
<form #myForm="ngForm" (ngSubmit)="save(myForm)">
<div class="form-group">
<label>name: </label>
<input name="heroName" [(ngModel)]="hero.name" placeholder="name" />
</div>
<button (click)="cancel(myForm)">Cancel</button>
<button type="submit">Save</button>
</form>
The cancel button calls the ngForm's resetForm() method.
cancel(myForm){
myForm.resetForm();
}
Repro steps
Change the hero name; Observe the h2 changes immediately proving that the bound object changed as well
Click cancel; Observe the name is cleared and the h2 changes because the hero.name is now null
I expected the cancel button to change the hero.name back to the original value. Is this how resetForm() is supposed to work? Is there a different way?
If you make a reset() method, where you set the default values, then you can call it whenever it's needed, as in ngOninit and reset button click:
ngOnInit(){
this.reset();
}
reset(){
this.hero = new Hero(1,'Plunker');
}
cancel(myForm){
this.reset();
}
DEMO
You can reunite cancel() and reset() by refactoring, but you may want keep it as is in case you add something else in cancel.
From the angular documentation, I guess the solution is to use a reactive form instead of a template driven form.
https://angular.io/guide/reactive-forms reads (emphasis :
In keeping with the reactive paradigm, the component preserves the
immutability of the data model, treating it as a pure source of
original values. Rather than update the data model directly, the
component extracts user changes and forwards them to an external
component or service, which does something with them (such as saving
them) and returns a new data model to the component that reflects the
updated model state.
Or put in tl;dr code:
form.email.$setValidity('conflict', false);
is too sticky for my simple serverside validation flow.
I'm trying to get the form to show good feedback in the event that the user enters an email address already in use by another customer. I'm running AngularJS v1.2 and have this template:
<form name="form">
<input name="email" type="email" ng-model="..." required>
</form>
<div ng-messages="form.email.$error">
<div ng-message="conflict">Email address already in use.</div>
</div>
In my controller, I'll handle the submit event and trigger the validation in my $http.post().error handler like this:
$http.post('api/form/submit/path/here').error(function(resp) {
if (resp.details === 'conflict')
$scope.form.email.$setValidity('conflict', false);
});
The problem is that when the user goes back and changes the value in the input field, the error message doesn't go away. It sticks around until I manually call $scope.form.setValidity();.
The docs say implement a custom directive with an ng-model dependency, but that seems super overkill for my purposes. I've also tried setting $scope.form.email.$valid = false; and $scope.form.email.$invalid = true; but those don't change the appearance of the textbox.
Nothing in your code modifies the conflict validation key, except for when $setValidity('conflict', false) is explicitly called. Since that is the only code setting the state of the conflict validation key and there is nothing else resetting it to true, it's expected behaviour that editing the textbox wouldn't reset its conflict validation state.
To get the behaviour that you want, you need to code for it. One way is to use ng-change.
<input name="email" type="email" ng-model="..." required ng-change="resetConflictState()">
$scope.resetConflictState = function() {
$scope.form.email.$setValidity('conflict', true);
}
I am displaying a validation symbol in the left nav of a page to indicate whether the form is valid or not. When I load the page initially the form's $valid attribute is set to true, then eventually it changes to false (as it should be given the retrieved input data). The result is my validation symbol flickering from valid to invalid. Is there any way to prevent this? Currently the validation symbol is tied to a valid attribute on the $scope, which gets set within a watch. Is there any logic that could be added to the watch to check if the form hasn't finished initializing or validating? Thanks!
Here is my current watch code. The valid attribute goes from undefined to true to false after a couple different watch cycles.
$scope.$watch( 'sections.' + section.sectionName + '.sectionForm.$valid', function( valid ) {
section.valid = valid;
}, true);
And the HTML to display the validation symbol:
<span ng-class="{ 'fa fa-check': section.valid,
'fa fa-warning': !section.valid}">
</span>
I think the problem is the $watch function. The first time you will set "section.valid" as undefined. You don't need to watch manually. Each form directive creates an instance of FormController. So, you can check the form validity directly in view.
<span ng-class="{'fa fa-check': sectionFormName.$valid, 'fa fa-warning': sectionFormName.$invalid}"></span>
Hi I have a form which does update on button click.
$scope.action = "Update";
var id = $routeParams.editId;
scope.item = updateRecord.get({ id: id });
Once the item is updated it doesn't remove the entered information in the form fields. I was wondering what is available in angularjs to add in the above code after udpating so that it also clears to form.
Thanks
You can reset a form by, $scope.formName.$setPristine(); but if you're binding a model object to your inputs, you need to take care of clearing those too, ie:
$scope.currentRecord={};
EDIT
As ToodoN-Mike pointed out, don't forget to set
$scope.formName.$setUntouched()
The $touched flag was introduced in angular 1.3.
At the bottom of your submit function's body run this code below.
// Reset the form model.
vm.project = {};
// Set back to pristine.
vm.form.$setPristine();
// Since Angular 1.3, set back to untouched state.
vm.form.$setUntouched();
"vm.form" is my form name.
For more info have a look at this docs page:
https://docs.angularjs.org/api/ng/type/form.FormController
This worked for me.
viewModel.data = {};
$scope.formName.$setUntouched();
$scope.formName.$setPristine();
1) To Remove the values in Form Fields and to reset you can use $setPristine();
$scope.formName.$setPristine();
2) Next, to set the form to Untouched State too use $setUntouched();
(If you have required fields in your form Fields and also if you are using ng-messages then if you don't use the below function those fields will show error.)
$scope.formName.$setUntouched();
I dont get the question, but maybe, you can clean the form in the Html component:
function: ngSubmit(), send the data.
taskName is the name of the field, also taskBody.
<form (ngSubmit)="onSubmit(taskName.value, taskBody.value); taskName.value=''; taskBody.value=''" #taskForm="ngForm">