Skip to content
This repository was archived by the owner on Feb 22, 2018. It is now read-only.

Commit 6a6e4ca

Browse files
matskorkirov
authored andcommitted
feat(ngControl): provide support for clearing errors states
1 parent d929109 commit 6a6e4ca

File tree

3 files changed

+141
-0
lines changed

3 files changed

+141
-0
lines changed

lib/directive/ng_control.dart

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,26 @@ abstract class NgControl implements AttachAware, DetachAware {
186186
if (hasRemovals) _parentControl.removeStates(this);
187187
}
188188

189+
/**
190+
* Removes all of the errors on the control and on any child controls and then sets the control to valid.
191+
*/
192+
void clearErrorStates() {
193+
errorStates.forEach((errorName, state) {
194+
element..removeClass(errorName + '-invalid')
195+
..removeClass(errorName + '-valid');
196+
197+
_parentControl.removeErrorState(this, errorName);
198+
});
199+
200+
errorStates.clear();
201+
202+
removeInfoState(this, NG_INVALID);
203+
204+
_controls.forEach((control) {
205+
control.clearErrorStates();
206+
});
207+
}
208+
189209
/**
190210
* Whether or not the control contains the given error.
191211
*
@@ -313,6 +333,7 @@ class NgNullControl implements NgControl {
313333
get parentControl => null;
314334

315335
String _getOppositeInfoState(String state) => null;
336+
void clearErrorStates() {}
316337
void addErrorState(NgControl control, String state) {}
317338
void removeErrorState(NgControl control, String state) {}
318339
void addInfoState(NgControl control, String state) {}

test/directive/ng_form_spec.dart

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,99 @@ void main() {
718718
expect(s.eval('myForm["name"].name')).toEqual("name");
719719
});
720720

721+
it("should clear all the error states from the entire form and all error-related CSS classes", (TestBed _) {
722+
Scope s = _.rootScope;
723+
s.context['name'] = 'cool';
724+
725+
var form = _.compile('<form name="myForm">'
726+
' <input type="text" ng-model="someModel" probe="i" name="name" />'
727+
'</form>');
728+
729+
NgForm formModel = s.context['myForm'];
730+
Probe probe = s.context['i'];
731+
NgModel inputModel = probe.directive(NgModel);
732+
var input = inputModel.element.node;
733+
734+
inputModel.addError('required');
735+
s.apply();
736+
737+
expect(form).toHaveClass('required-invalid');
738+
expect(formModel.hasErrorState('required')).toBe(true);
739+
740+
expect(input).toHaveClass('required-invalid');
741+
expect(inputModel.hasErrorState('required')).toBe(true);
742+
743+
formModel.clearErrorStates();
744+
s.apply();
745+
746+
expect(form).not.toHaveClass('required-invalid');
747+
expect(form).not.toHaveClass('ng-invalid');
748+
expect(formModel.hasErrorState('required')).toBe(false);
749+
750+
expect(input).not.toHaveClass('required-invalid');
751+
expect(input).not.toHaveClass('ng-invalid');
752+
expect(inputModel.hasErrorState('required')).toBe(false);
753+
});
754+
755+
it("should clear all errors from the fieldset and properly update the parent form\'s errors", (TestBed _) {
756+
Scope s = _.rootScope;
757+
s.context['name'] = 'cool';
758+
759+
var form = _.compile('<form name="myForm">'
760+
' <input type="text" ng-model="anotherModel" probe="x" />' +
761+
' <fieldset probe="f">' +
762+
' <input type="text" ng-model="someModel" probe="i" name="name" />'
763+
' </fieldset>' +
764+
'</form>');
765+
766+
NgForm formModel = s.context['myForm'];
767+
NgModel inputModel = s.context['i'].directive(NgModel);
768+
var input = inputModel.element.node;
769+
770+
NgModel anotherModel = s.context['x'].directive(NgModel);
771+
var anotherInput = anotherModel.element.node;
772+
773+
NgForm fieldsetModel = s.context['f'].directive(NgForm);
774+
var fieldset = fieldsetModel.element.node;
775+
776+
inputModel.addError("required");
777+
anotherModel.addError("required");
778+
s.apply();
779+
780+
expect(form).toHaveClass('required-invalid');
781+
expect(formModel.hasErrorState('required')).toBe(true);
782+
expect(fieldset).toHaveClass('required-invalid');
783+
expect(fieldsetModel.hasErrorState('required')).toBe(true);
784+
785+
expect(input).toHaveClass('required-invalid');
786+
expect(inputModel.hasErrorState('required')).toBe(true);
787+
expect(anotherInput).toHaveClass('required-invalid');
788+
expect(anotherModel.hasErrorState('required')).toBe(true);
789+
790+
fieldsetModel.clearErrorStates();
791+
s.apply();
792+
793+
expect(form).toHaveClass('required-invalid');
794+
expect(anotherInput).toHaveClass('required-invalid');
795+
796+
expect(fieldset).not.toHaveClass('required-invalid');
797+
expect(input).not.toHaveClass('required-invalid');
798+
799+
expect(fieldset).not.toHaveClass('ng-invalid');
800+
expect(form).toHaveClass('ng-invalid');
801+
802+
expect(fieldsetModel.hasErrorState('required')).toBe(false);
803+
expect(inputModel.hasErrorState('required')).toBe(false);
804+
expect(anotherModel.hasErrorState('required')).toBe(true);
805+
expect(formModel.hasErrorState('required')).toBe(true);
806+
807+
anotherModel.removeError("required");
808+
s.apply();
809+
810+
expect(formModel.hasErrorState('required')).toBe(false);
811+
expect(form).not.toHaveClass('required-invalid');
812+
});
813+
721814
describe('regression tests: form', () {
722815
beforeEachModule((Module module) {
723816
module.bind(NgForm);

test/directive/ng_model_spec.dart

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,6 +1326,33 @@ void main() {
13261326

13271327
expect(model.hasErrorState('big-failure')).toBe(false);
13281328
});
1329+
1330+
it("model.clearErrorState() should erase all the errors and set the model to valid", (TestBed _) {
1331+
Scope s = _.rootScope;
1332+
1333+
_.compile('<input type="text" ng-model="myModel" probe="i" />');
1334+
_.rootScope.apply('myModel = "animal"');
1335+
1336+
NgModel inputModel = s.context['i'].directive(NgModel);
1337+
var input = inputModel.element.node;
1338+
1339+
inputModel.addError("required");
1340+
inputModel.addError("minlength");
1341+
s.apply();
1342+
1343+
expect(inputModel.hasErrorState("required")).toBe(true);
1344+
expect(inputModel.hasErrorState("minlength")).toBe(true);
1345+
expect(inputModel.invalid).toBe(true);
1346+
expect(inputModel.valid).toBe(false);
1347+
1348+
inputModel.clearErrorStates();
1349+
s.apply();
1350+
1351+
expect(inputModel.hasErrorState("required")).toBe(false);
1352+
expect(inputModel.hasErrorState("minlength")).toBe(false);
1353+
expect(inputModel.invalid).toBe(false);
1354+
expect(inputModel.valid).toBe(true);
1355+
});
13291356
});
13301357

13311358
describe('text-like events', () {

0 commit comments

Comments
 (0)