Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Commit

Permalink
feat(form.FormController): add $getControls()
Browse files Browse the repository at this point in the history
Closes #16601
Fixes #14749
Closes #14517
Closes #13202
  • Loading branch information
Narretz committed Jun 18, 2018
1 parent a47247b commit c9d1e69
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 0 deletions.
25 changes: 25 additions & 0 deletions src/ng/directive/form.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/
var nullFormCtrl = {
$addControl: noop,
$getControls: valueFn([]),
$$renameControl: nullFormRenameControl,
$removeControl: noop,
$setValidity: noop,
Expand Down Expand Up @@ -159,6 +160,30 @@ FormController.prototype = {
control.$$parentForm = this;
},

/**
* @ngdoc method
* @name form.FormController#$getControls
* @returns {Array} the controls that are currently part of this form
*
* @description
* This method returns a **shallow copy** of the controls that are currently part of this form.
* The controls can be instances of {@link form.FormController `FormController`}
* ({@link ngForm "child-forms"}) and of {@link ngModel.NgModelController `NgModelController`}.
* If you need access to the controls of child-forms, you have to call `$getControls()`
* recursively on them.
* This can be used for example to iterate over all controls to validate them.
*
* The controls can be accessed normally, but adding to, or removing controls from the array has
* no effect on the form. Instead, use {@link form.FormController#$addControl `$addControl()`} and
* {@link form.FormController#$removeControl `$removeControl()`} for this use-case.
* Likewise, adding a control to, or removing a control from the form is not reflected
* in the shallow copy. That means you should get a fresh copy from `$getControls()` every time
* you need access to the controls.
*/
$getControls: function() {
return shallowCopy(this.$$controls);
},

// Private API: rename a form control
$$renameControl: function(control, newName) {
var oldName = control.$name;
Expand Down
46 changes: 46 additions & 0 deletions test/ng/directive/formSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1200,6 +1200,52 @@ describe('form', function() {
});
});

describe('$getControls', function() {
it('should return an empty array if the controller has no controls', function() {
doc = $compile('<form name="testForm"></form>')(scope);

scope.$digest();

var formCtrl = scope.testForm;

expect(formCtrl.$getControls()).toEqual([]);
});

it('should return a shallow copy of the form controls', function() {
doc = $compile(
'<form name="testForm">' +
'<input ng-model="named" name="foo">' +
'<div ng-form>' +
'<input ng-model="named" name="foo">' +
'</div>' +
'</form>')(scope);

scope.$digest();

var form = doc,
formCtrl = scope.testForm,
formInput = form.children('input').eq(0),
formInputCtrl = formInput.controller('ngModel'),
nestedForm = form.find('div'),
nestedFormCtrl = nestedForm.controller('form'),
nestedInput = nestedForm.children('input').eq(0),
nestedInputCtrl = nestedInput.controller('ngModel');

var controls = formCtrl.$getControls();

expect(controls).not.toBe(formCtrl.$$controls);

controls.push('something');
expect(formCtrl.$$controls).not.toContain('something');

expect(controls[0]).toBe(formInputCtrl);
expect(controls[1]).toBe(nestedFormCtrl);

var nestedControls = controls[1].$getControls();

expect(nestedControls[0]).toBe(nestedInputCtrl);
});
});

it('should rename nested form controls when interpolated name changes', function() {
scope.idA = 'A';
Expand Down

0 comments on commit c9d1e69

Please sign in to comment.