AngularJS ngModelOptions updateOn 'submit' validateOn 'default' - angularjs

Is there any way how to trigger validation when using ngModelOptions? My use-case is to have a form with all fields updating the ngModel on submit (due to the fact that I would like to revert the whole form when user clicks on Cancel button). Having this, I cannot validate my fields instantly. Fields are validated just when the model is updated thus onSubmit. Is there any build in solution or should I use my custom implementation?
<form name="editForm" ng-submit="edit()">
<input type="text" name="text" required maxlength="140" ng-model="myObject.text"
ng-model-options="{ updateOn: 'submit' }" />
<button type="submit" ng-disabled="editForm.$invalid">
Save
</button>
</form>

What I usually do is commit the form's view value on the js code and if form is invalid then do not submit. Thus in HTML I add an on-click attribute like:
<button on-click="edit(editForm)">
And then on the javascript
edit = function(editForm) {
editForm.$commitViewValue;
if (editForm.$valid) { // submit code }
}

Related

Angular ngModelOptions - bind value to model only when button is clicked

I have an input field that is bound to a model object, which I don't want to bind until the user clicks a button. I went through ng-model-option and updateOn, but seems they trigger only on out of the box JS events like blur and focus.
<input ng-model="modelobject" ng-model-options="{updateOn: confirmButtonClick}">
<button id="confirmButton" role="confirm" ng-click="confirmButtonClick == true" class="confirm-btn">Confirm</button>
How can I make the value bind to the model only upon the click of the button or a custom function? Would I need to write a custom directive?
You could do solve your problem by wrapping you fields inside a form and then update ng-model on submit of a form like ng-model-options="{updateOn: 'submit'}".
HTML
<form name="myForm">
<input ng-model="modelobject" ng-model-options="{updateOn: 'submit'}">
<button id="confirmButton" role="confirm" class="confirm-btn">
Confirm
</button>
</form>
Working Plunkr

Can you have a custom trigger for updating ng-model fields in Angular?

Angular has a number of options for delaying the update to a model based on events in an input field:
<input type="text" name="username"
ng-model="user.name"
ng-model-options="{updateOn: 'default blur',
debounce: {default: 500, blur: 0} }" />
(See ng-model options)
Can you delay all the commits to the object based on a user confirmation?
The basic options that Angular offers allows the editing of an input form to be decoupled from the actual update of the model. There are some nice bonuses with this in that we can roll the value of the object back if we decide to cancel that update.
However, I would like to delay the update of the model, not based on an event on the input field but instead based on someone clicking a submit button.
I would ideally like a form where the user can update the inputs (let's say for a .user form, any bound elements in the page {{user.first_name}} etc. do not update and then when the user clicks submit those updates get committed to the model.
Equally if the user clicks "Cancel" the updates can all be rolled back.
Ideal setup:
<input type="text" name="username"
ng-model="user.name"
ng-model-options="{updateOn: 'myCustomEvent' }" />
<button onClick="broadCastMyCustomEventIntoForm()">Save changes</>
Is this possible?
Yes it is possible as long as you bind your input fields to custom event and then trigger that custom event on user confirmation.
http://plnkr.co/edit/GgsaFbIurhx88p6HJgkT?p=preview
<input bind-event type="text" name="userName" ng-model="user.name" ng-model-options="{ updateOn: 'customEvent'}" />
//bind-event directive for input fields.
.directive('bindEvent', function() {
return {
restrict: 'EAC',
controller: function($scope, $element, $attrs) {
$element.on('customEvent', function() {
console.log('custom event is triggered');
});
}
};
});
//trigger the event on submit.
$scope.click = function() {
$element.find( "input" ).triggerHandler( "customEvent" );
}
I found a simple way to do this today using $emit. I was trying to apply filter on a button click, rather than instantly(default behavior):
<input ng-model="myFilter.minPrice" ng-model-options="{updateOn: 'filterBtnClicked'}">
...
<button type="button" ng-click="$emit('filterBtnClicked')">Filter</button>
Model value is applied only after button is clicked.
I don't think angular natively support the use case you describe.
But it shouldn't be difficult get it done, exposing a copy of the real model to the view and copy the changes to the real model on the click event handler.

Angular.js: Set form fields "dirty" upon submission

How can I make a form input to become dirty as the form is submitted?
This is needed so that the input fields with an $error can be
Example:
name: <input type="text"
ng-model="user.name"
ng-model-options="{ updateOn: 'blur' }"
name="uName"
required /><br/>
As the form is submitted, I want this field - if left blank - to be rendered using the "invalid & dirty" style:
.css-form input.ng-invalid.ng-dirty {
background-color: #FA787E;
}
Disable the submission button until form is dirty and the form items are valid.
<button type="submit" class="btn btn-primary" ng-disabled="myFrmName.$invalid || !myFrmName.$dirty">Submit Form</button>
Using ng-disabled will disable the form submission button while the form is $invalid or the form has yet to be touched (not $dirty).
EDIT
I usually do something like this to display an error next to the required field:
<input type="text" name="myField" required ng-class="{true : 'has-error'}[hasError(myFrmName.myField.$error.required,myFrmName.myField.$dirty)]>
<span ng-if="hasError(myFrmName.myField.$error.required,myFrmName.myField.$dirty)">Required!</span>
Then in your controller:
$scope.hasError = function(e,d){ // e = $error, d = $dirty
if(angular.isDefined(e))
return e && d;
return false;
} // end hasError
Example with ngMessages (Angular 1.3)
<input type="text" name="myField ng-model="fields.myField" ng-class="{true : 'has-error'}[hasError(myFrmName.myField.$error.required,myFrmName.myField.$dirty)] required>
<ng-messages for="myFrmName.myField.$error" ng-if="myFrmName.myField.$dirty">
<ng-message when="required" class="text-danger">The field is required!</ng-message>
</ng-messages>
The great thing about ngMessages is that all you need to do is add more <ng-message> tags for each type of validation for the field and just change the when attribute approrpriately.
<ng-message when="minlength">Your entry is too short.</ng-message>
Angular will display the correct message based upon whether or not the when is in the $error object for the field.
You can use $submitted flag of the form to highlight the field if the form is submitted and is empty.
<input type="text"
ng-model="user.name"
ng-model-options="{ updateOn: 'blur' }"
name="uName"
ng-class={'has-error': yourFormName.$submitted && !yourFormName.uName.$valid}
required />
Or I guess just setting the form's dirty flag to true in your controller might do the same work. But I believe this implicitly changes the DOM as it adds a class to form which is not a good practice in angular.
$scope.yourForm.$dirty = true;
in case you would like to do that programatically, there is a method named "$setDirty()" you could use for that purpose.
https://docs.angularjs.org/api/ng/type/form.FormController

Make Backbone ignore a button or button type

I'm building a form and within that form is a secondary function that I wish to run. However, when I click the button for my secondary function, backbone fires and runs validation over the whole form. How do I either:
a) Make Backbone ignore that specific button and do nothing when it's clicked
or
b) (Preferred) Tie Backbone validation to only the form submit button or the button type "submit".
Example:
<form name="myForm" >
<input type="text" name="yourName" ng-model="yourName" required />
<input type="text" name="postcode" ng-model="postcode" required />
<button id="checkPostcode" type="button" >Check Postcode</button>
<button id="submit" type="submit" >Submit</button>
</form>
In this case, I only wish Backbone to run validation when the submit button is pressed, so that I can run my checkPostcode function without interference.
Thanks :)
You should add an eventListener to the button and prevent the default. Something like this:
var view = Backbone.View.extend({
events: {
"click #checkPostcode": "checkPostcode"
},
checkPostcode: function(event) {
event.preventDefault();
// the actual check would go here
}
});

custom validation in angularJS

I am new to AngularJS.
In the following fiddle, when user clicks on "This submit triggers validation. But I wanted to put this button at the end of the page" button. I could see alert/error but I want to show a custom message, which I am struggling to do it.
Header inputs:
<input type="name" ng-model="sample" required/>
<input type="name" ng-model="sampleX" required/>
<input type="submit" value="This submit triggers validation. But I wanted to put this button at the end of the page"/>
</form>
<hr/>
Some other form here. Think line items
<hr />
<a class="btn" ng-click="triggerSubmit()">Wanted this submit to trigger the validation to the form on which this button doesn't belong, e.g. trigger to header</a>
js fiddle link
http://jsfiddle.net/unWF3/6/
Thanks,
Kalyan Basa
To disable native browser validation add novalidate attribute to form element:
<form novalidate submit-on="myEvent" ng-submit="onSubmitted()">

Resources