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

Commit 634c62b

Browse files
matskomhevery
authored andcommitted
feat(forms): provide support for touch and untouched control flags
Closes #591
1 parent 768a809 commit 634c62b

File tree

5 files changed

+101
-4
lines changed

5 files changed

+101
-4
lines changed

lib/directive/ng_control.dart

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ abstract class NgControl implements NgDetachAware {
55
static const NG_INVALID_CLASS = "ng-invalid";
66
static const NG_PRISTINE_CLASS = "ng-pristine";
77
static const NG_DIRTY_CLASS = "ng-dirty";
8+
static const NG_TOUCHED_CLASS = "ng-touched";
9+
static const NG_UNTOUCHED_CLASS = "ng-untouched";
810
static const NG_SUBMIT_VALID_CLASS = "ng-submit-valid";
911
static const NG_SUBMIT_INVALID_CLASS = "ng-submit-invalid";
1012

@@ -13,6 +15,8 @@ abstract class NgControl implements NgDetachAware {
1315
bool _pristine;
1416
bool _valid;
1517
bool _invalid;
18+
bool _touched;
19+
bool _untouched;
1620

1721
final Scope _scope;
1822
final NgControl _parentControl;
@@ -26,6 +30,8 @@ abstract class NgControl implements NgDetachAware {
2630
: _parentControl = injector.parent.get(NgControl)
2731
{
2832
pristine = true;
33+
untouched = true;
34+
2935
_scope.on('submitNgControl').listen((e) => _onSubmit(e.data));
3036
}
3137

@@ -37,6 +43,7 @@ abstract class NgControl implements NgDetachAware {
3743

3844
reset() {
3945
_scope.broadcast('resetNgModel');
46+
untouched = true;
4047
}
4148

4249
_onSubmit(bool valid) {
@@ -91,6 +98,25 @@ abstract class NgControl implements NgDetachAware {
9198
element.classes..remove(NG_VALID_CLASS)..add(NG_INVALID_CLASS);
9299
}
93100

101+
get touched => _touched;
102+
set touched(value) {
103+
_touched = true;
104+
_untouched = false;
105+
106+
element.classes..remove(NG_UNTOUCHED_CLASS)..add(NG_TOUCHED_CLASS);
107+
108+
//as soon as one of the controls/models is touched
109+
//then all of the parent controls are touched as well
110+
_parentControl.touched = true;
111+
}
112+
113+
get untouched => _untouched;
114+
set untouched(value) {
115+
_touched = false;
116+
_untouched = true;
117+
element.classes..remove(NG_TOUCHED_CLASS)..add(NG_UNTOUCHED_CLASS);
118+
}
119+
94120
/**
95121
* Registers a form control into the form for validation.
96122
*
@@ -158,7 +184,7 @@ abstract class NgControl implements NgDetachAware {
158184
}
159185

160186
class NgNullControl implements NgControl {
161-
var _name, _dirty, _valid, _invalid, _pristine, _element;
187+
var _name, _dirty, _valid, _invalid, _pristine, _element, _touched, _untouched;
162188
var _controls, _scope, _parentControl, _controlName;
163189
var errors, _controlByName;
164190
dom.Element element;
@@ -185,6 +211,12 @@ class NgNullControl implements NgControl {
185211
get invalid => null;
186212
set invalid(value) {}
187213

214+
get touched => null;
215+
set touched(value) {}
216+
217+
get untouched => null;
218+
set untouched(value) {}
219+
188220
reset() => null;
189221
detach() => null;
190222

lib/directive/ng_form.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class NgForm extends NgControl implements Map<String, NgControl> {
3939
element.onSubmit.listen((event) {
4040
event.preventDefault();
4141
_scope.broadcast('submitNgControl', valid == null ? false : valid);
42+
reset();
4243
});
4344
}
4445
}

lib/directive/ng_model.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class NgModel extends NgControl implements NgAttachAware {
4545
}
4646

4747
reset() {
48+
untouched = true;
4849
modelValue = _lastValue;
4950
}
5051

@@ -203,7 +204,12 @@ class InputTextLikeDirective {
203204
};
204205
inputElement
205206
..onChange.listen(processValue)
206-
..onInput.listen(processValue);
207+
..onInput.listen(processValue)
208+
..onBlur.listen((e) {
209+
if(ngModel.touched == null || ngModel.touched == false) {
210+
ngModel.touched = true;
211+
}
212+
});
207213
}
208214

209215
processValue([_]) {

test/directive/ng_form_spec.dart

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,46 @@ describe('form', () {
362362
expect(model.modelValue).toEqual('animal');
363363
expect(model.viewValue).toEqual('animal');
364364
}));
365+
366+
it('should set the form control to be untouched when the model is reset or submitted', inject((TestBed _) {
367+
var form = _.compile('<form name="duperForm">' +
368+
' <input type="text" ng-model="myModel" probe="i" />' +
369+
'</form>');
370+
var model = _.rootScope.context['i'].directive(NgModel);
371+
var input = model.element;
372+
373+
NgForm formModel = _.rootScope.context['duperForm'];
374+
375+
expect(formModel.touched).toBe(false);
376+
expect(formModel.untouched).toBe(true);
377+
expect(form.classes.contains('ng-touched')).toBe(false);
378+
expect(form.classes.contains('ng-untouched')).toBe(true);
379+
380+
_.triggerEvent(input, 'blur');
381+
382+
expect(formModel.touched).toBe(true);
383+
expect(formModel.untouched).toBe(false);
384+
expect(form.classes.contains('ng-touched')).toBe(true);
385+
expect(form.classes.contains('ng-untouched')).toBe(false);
386+
387+
formModel.reset();
388+
389+
expect(formModel.touched).toBe(false);
390+
expect(formModel.untouched).toBe(true);
391+
expect(form.classes.contains('ng-touched')).toBe(false);
392+
expect(form.classes.contains('ng-untouched')).toBe(true);
393+
394+
_.triggerEvent(input, 'blur');
395+
396+
expect(formModel.touched).toBe(true);
397+
398+
_.triggerEvent(form, 'submit');
399+
400+
expect(formModel.touched).toBe(false);
401+
expect(formModel.untouched).toBe(true);
402+
expect(form.classes.contains('ng-touched')).toBe(false);
403+
expect(form.classes.contains('ng-untouched')).toBe(true);
404+
}));
365405
});
366406

367407
describe('regression tests: form', () {

test/directive/ng_model_spec.dart

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -707,8 +707,8 @@ describe('ng-model', () {
707707

708708
var model = probe.directive(NgModel);
709709

710-
var input1 = element.query("#on");
711-
var input2 = element.query("#off");
710+
var input1 = element.querySelector("#on");
711+
var input2 = element.querySelector("#off");
712712

713713
expect(model.pristine).toEqual(true);
714714
expect(model.dirty).toEqual(false);
@@ -1021,6 +1021,24 @@ describe('ng-model', () {
10211021
expect(model.modelValue).toEqual('animal');
10221022
expect(model.viewValue).toEqual('animal');
10231023
});
1024+
1025+
it('should set the model to be untouched when the model is reset', () {
1026+
var input = _.compile('<input type="text" ng-model="myModel" probe="i" />');
1027+
var model = _.rootScope.context['i'].directive(NgModel);
1028+
1029+
expect(model.touched).toBe(false);
1030+
expect(model.untouched).toBe(true);
1031+
1032+
_.triggerEvent(input, 'blur');
1033+
1034+
expect(model.touched).toBe(true);
1035+
expect(model.untouched).toBe(false);
1036+
1037+
model.reset();
1038+
1039+
expect(model.touched).toBe(false);
1040+
expect(model.untouched).toBe(true);
1041+
});
10241042
});
10251043
});
10261044

0 commit comments

Comments
 (0)