AngularJS directive that works like ng-model
but accept changes only when form is submitted (otherwise changes are cancelled).
##UPDATE!!! As of Angular 1.3 there is ngModelOptions directive that allows to achive the same behavior natively
<form name="userForm">
<input type="text" ng-model="user.name" ng-model-options="{ updateOn: 'submit' }" name="userName">
<button type="submit">save</button>
<button type="button" ng-click="userForm.userName.$rollbackViewValue();">cancel</button>
</form>
jsfiddle: http://jsfiddle.net/8btk5/104/ So you don't need lazy-model any more!
AngularJS 2-way binding is good feature: you change model - and all views are updated instantly.
But when dealing with forms I often need more transactional way: input something and accept changes or decline it. Official way to do it requires additional code in controller: create copy of model, link it with form and write changes back to original model when form is submitted (see http://docs.angularjs.org/guide/forms).
Being too lazy, I tried to put all that stuff into lazy-model directive.
- Create form with submit and reset buttons
- In controls use
lazy-model
instead ofng-model
<form>
<input type="text" lazy-model="user.name">
<button type="submit">save</button>
<button type="reset">cancel</button>
</form>
Now you can change username, but it will be saved to model only when you press save.
If you press cancel - your changes will be declined.
Try out demo: http://jsfiddle.net/8btk5/6/
It can be useful for popup forms and modal dialogs.
For example, popup form:
<form ng-submit="formVisible=false" ng-show="formVisible">
<input type="text" lazy-model="user.name">
<button type="submit">save</button>
<button type="reset" ng-click="formVisible=false">cancel</button>
</form>
<button ng-click="formVisible=true" ng-show="!formVisible">show form</button>
Live demo: http://jsfiddle.net/8btk5/7/
Basically there are two ways of validation:
Use normal AngularJS validation described in docs.
For example, ng-maxlength
validator:
<form name="frm" ng-submit="submit()" ng-show="formVisible">
...
<input type="text" name="username" lazy-model="user.name" ng-maxlength="10">
And check form.$valid
in submit handler in controller:
$scope.submit = function() {
if ($scope.frm.$valid) {
$scope.formVisible = false;
}
};
Live demo: http://jsfiddle.net/8btk5/8/
Alternatively, you can perform all validations inside submit
handler and accept or decline
changes by setting validity via $setValidity
method. Don't forget to define name
attribute
of form and controls.
<form name="frm" ng-submit="submit()" ng-show="formVisible">
...
<input type="text" name="username" lazy-model="user.name">
...
<button type="reset" ng-click="cancel()">cancel</button>
In controller you should define both submit
and cancel
handlers:
$scope.submit = function() {
if ($scope.frm.username.$modelValue.length > 10) {
$scope.frm.username.$setValidity('maxlength', false);
} else {
$scope.frm.username.$setValidity('maxlength', true);
$scope.formVisible = false;
}
};
$scope.cancel = function() {
$scope.frm.username.$setValidity('maxlength', true);
$scope.formVisible = false;
}
Live demo: http://jsfiddle.net/8btk5/10/
Please note that in ng-submit
hook original models are not updated yet.
You may use it for validation but not for sending data on server.
To send data there is special attribute of <form>
called lazy-submit
.
Inside this hook models are updated and you can freely manipulate your models.
<form name="frm" lazy-submit="save()" ng-show="formVisible">
...
<input type="text" name="username" lazy-model="user.name" ng-maxlength="10">
In controller:
$scope.save = function() {
$scope.formVisible = false;
sendToServer($scope.user);
};
Live demo: http://jsfiddle.net/8btk5/12/
- Install via bower:
bower install lazy-model
or dowload manually lazyModel.js.
-
Include lazyModel.js and set app dependency:
var app = angular.module("app", ["lazyModel"]);