Skip to content

Commit ee36686

Browse files
author
Gonzalo Ruiz de Villa
committed
feat(form): add support for ngFormOptions attribute and form isolation
Child forms propagate always their state to its parent form. Following the pattern of ngModelOptions a new optional attribute is defined for forms, ngFormOptions that will allow to define now if the form is isolated from its parent. In the future, if more options are needed this new attribute may be the place to define them. Options are exposed in the controller, but the isolated property is read only when the NgFormController is executed, so the behavior won't change if its value is changed later. It maybe used like this: <ng:form name="parent"> <ng:form name="child" ng-form-options="{isolated:true}"> <input ng:model="modelA" name="inputA"> <input ng:model="modelB" name="inputB"> </ng:form> </ng:form> Closes: angular#5858
1 parent 119ace4 commit ee36686

File tree

2 files changed

+47
-1
lines changed

2 files changed

+47
-1
lines changed

src/ng/directive/form.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,11 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
6464
var form = this,
6565
controls = [];
6666

67-
var parentForm = form.$$parentForm = element.parent().controller('form') || nullFormCtrl;
67+
form.$options = $scope.$eval(attrs.ngFormOptions) || {};
68+
69+
var parentForm = form.$$parentForm =
70+
(!form.$options.isolated && element.parent().controller('form'))
71+
|| nullFormCtrl;
6872

6973
// init state
7074
form.$error = {};
@@ -296,6 +300,10 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
296300
*
297301
* @param {string=} ngForm|name Name of the form. If specified, the form controller will be published into
298302
* related scope, under this name.
303+
* @param {Object} ngFormOptions options to apply to the current form.
304+
* - `isolated`: boolean value which indicates that the form should not propagate its state
305+
* to the parent form. By default, child forms are not isolated and propagate their state
306+
* ($dirty, $pristine, $valid, ...) to its parent form.
299307
*
300308
*/
301309

test/ng/directive/formSpec.js

+38
Original file line numberDiff line numberDiff line change
@@ -870,6 +870,43 @@ describe('form', function() {
870870
expect(scope.form.$submitted).toBe(false);
871871
});
872872
});
873+
874+
describe('ngFormOptions attributes', function() {
875+
it('should allow to isolate forms', function() {
876+
doc = jqLite(
877+
'<ng:form name="parent">' +
878+
'<ng:form name="child" ng-form-options="{isolated:true}">' +
879+
'<input ng:model="modelA" name="inputA">' +
880+
'<input ng:model="modelB" name="inputB">' +
881+
'</ng:form>' +
882+
'</ng:form>');
883+
$compile(doc)(scope);
884+
885+
var parent = scope.parent,
886+
child = scope.child,
887+
inputA = child.inputA,
888+
inputB = child.inputB;
889+
890+
inputA.$setValidity('MyError', false);
891+
inputB.$setValidity('MyError', false);
892+
expect(parent.$error.MyError).toBeFalsy();
893+
expect(child.$error.MyError).toEqual([inputA, inputB]);
894+
895+
inputA.$setValidity('MyError', true);
896+
expect(parent.$error.MyError).toBeFalsy();
897+
expect(child.$error.MyError).toEqual([inputB]);
898+
899+
inputB.$setValidity('MyError', true);
900+
expect(parent.$error.MyError).toBeFalsy();
901+
expect(child.$error.MyError).toBeFalsy();
902+
903+
child.$setDirty();
904+
expect(parent.$dirty).toBeFalsy();
905+
906+
child.$setSubmitted();
907+
expect(parent.$submitted).toBeFalsy();
908+
});
909+
});
873910
});
874911

875912
describe('form animations', function() {
@@ -947,4 +984,5 @@ describe('form animations', function() {
947984
assertValidAnimation($animate.queue[2], 'addClass', 'ng-valid-custom-error');
948985
assertValidAnimation($animate.queue[3], 'removeClass', 'ng-invalid-custom-error');
949986
}));
987+
950988
});

0 commit comments

Comments
 (0)