diff --git a/angular_forms/CHANGELOG.md b/angular_forms/CHANGELOG.md index 778f089d1c..3b69ea6bee 100644 --- a/angular_forms/CHANGELOG.md +++ b/angular_forms/CHANGELOG.md @@ -3,9 +3,6 @@ * Add `MemorizedForm` directive. This is a form that will not remove controls if the control is taken out of the view, for example with a [NgIf]. -* Add `disabled` state to `AbstractControl` models. Note: This is not yet - supported in the template-driven directives. - ## Breaking Changes * Remove `optionals` param from `ControlGroup` constructor. This will soon be diff --git a/angular_forms/lib/src/model.dart b/angular_forms/lib/src/model.dart index f537f96810..21a672dba5 100644 --- a/angular_forms/lib/src/model.dart +++ b/angular_forms/lib/src/model.dart @@ -31,10 +31,6 @@ abstract class AbstractControl { /// occurring and errors are not yet available for the input value. static const PENDING = 'PENDING'; - /// Indicates that a FormControl is disabled, i.e. that the control is exempt - /// from ancestor calculations of validity or value. - static const DISABLED = 'DISABLED'; - ValidatorFn validator; T _value; final _valueChanges = new StreamController.broadcast(); @@ -58,10 +54,6 @@ abstract class AbstractControl { bool get valid => _status == VALID; - bool get disabled => _status == DISABLED; - - bool get enabled => !disabled; - /// Returns the errors of this control. Map get errors => _errors; @@ -105,38 +97,6 @@ abstract class AbstractControl { } } - void markAsDisabled({bool onlySelf, bool emitEvent}) { - onlySelf = onlySelf == true; - emitEvent = emitEvent ?? true; - - _status = DISABLED; - - _forEachChild( - (c) => c.markAsDisabled(onlySelf: onlySelf, emitEvent: emitEvent)); - onUpdate(); - - if (emitEvent) _emitEvent(); - - _updateAncestors(onlySelf: onlySelf); - } - - void markAsEnabled({bool onlySelf, bool emitEvent}) { - onlySelf = onlySelf == true; - emitEvent = emitEvent ?? true; - _status = VALID; - _forEachChild( - (c) => c.markAsEnabled(onlySelf: onlySelf, emitEvent: emitEvent)); - updateValueAndValidity(onlySelf: true, emitEvent: emitEvent); - _updateAncestors(onlySelf: onlySelf); - } - - void _updateAncestors({bool onlySelf}) { - if (_parent != null && !onlySelf) { - _parent.updateValueAndValidity(); - // TODO(alorenzen): Update parent pristine and touched. - } - } - void setParent(AbstractControl parent) { _parent = parent; } @@ -147,17 +107,15 @@ abstract class AbstractControl { onUpdate(); _errors = _runValidator(); _status = _calculateStatus(); - if (emitEvent) _emitEvent(); + if (emitEvent) { + _valueChanges.add(_value); + _statusChanges.add(_status); + } if (_parent != null && !onlySelf) { _parent.updateValueAndValidity(onlySelf: onlySelf, emitEvent: emitEvent); } } - void _emitEvent() { - _valueChanges.add(_value); - _statusChanges.add(_status); - } - Map _runValidator() => validator != null ? validator(this) : null; @@ -242,7 +200,6 @@ abstract class AbstractControl { if (_errors != null) return INVALID; if (_anyControlsHaveStatus(PENDING)) return PENDING; if (_anyControlsHaveStatus(INVALID)) return INVALID; - if (_allControlsHaveStatus(DISABLED)) return DISABLED; return VALID; } @@ -254,9 +211,6 @@ abstract class AbstractControl { void onUpdate(); bool _anyControlsHaveStatus(String status); - bool _allControlsHaveStatus(String status); - - void _forEachChild(void callback(AbstractControl c)); } /// Defines a part of a form that cannot be divided into other controls. @@ -315,12 +269,6 @@ class Control extends AbstractControl { @override bool _anyControlsHaveStatus(String status) => false; - @override - bool _allControlsHaveStatus(String status) => this.status == status; - - @override - void _forEachChild(void callback(AbstractControl c)) {} - /// Register a listener for change events. /// /// Used internally to connect the model with the [ValueAccessor] which will @@ -344,6 +292,7 @@ class Control extends AbstractControl { /// [ControlArray] can also contain other controls, but is of variable length. class ControlGroup extends AbstractControl> { final Map controls; + final Map _optionals = {}; ControlGroup(this.controls, [ValidatorFn validator]) : super(validator) { _setParentForControls(this, controls.values); @@ -362,16 +311,19 @@ class ControlGroup extends AbstractControl> { /// Mark the named control as non-optional. void include(String controlName) { - controls[controlName]?.markAsEnabled(); + _optionals[controlName] = true; + updateValueAndValidity(); } /// Mark the named control as optional. void exclude(String controlName) { - controls[controlName]?.markAsDisabled(); + _optionals[controlName] = false; + updateValueAndValidity(); } /// Check whether there is a control with the given name in the group. - bool contains(String controlName) => controls.containsKey(controlName); + bool contains(String controlName) => + controls.containsKey(controlName) && _included(controlName); @override void onUpdate() { @@ -380,38 +332,22 @@ class ControlGroup extends AbstractControl> { @override bool _anyControlsHaveStatus(String status) { - for (var name in controls.keys) { - if (contains(name) && controls[name].status == status) return true; - } - return false; - } - - @override - bool _allControlsHaveStatus(String status) { - for (var name in controls.keys) { - if (!contains(name) || controls[name].status != status) return false; - } - return true; - } - - @override - void _forEachChild(void callback(AbstractControl c)) { - for (var control in controls.values) { - callback(control); - } + return controls.keys.any((name) { + return contains(name) && controls[name].status == status; + }); } Map _reduceValue() { final res = {}; - for (var name in controls.keys) { - if (_included(name) || disabled) { - res[name] = controls[name].value; + controls.forEach((name, control) { + if (_included(name)) { + res[name] = control.value; } - } + }); return res; } - bool _included(String controlName) => controls[controlName]?.enabled ?? false; + bool _included(String controlName) => _optionals[controlName] != false; } /// Defines a part of a form, of variable length, that can contain other @@ -469,36 +405,12 @@ class ControlArray extends AbstractControl { @override void onUpdate() { - _value = []; - for (var control in controls) { - if (control.enabled || disabled) { - _value.add(control.value); - } - } - } - - @override - bool _anyControlsHaveStatus(String status) { - for (var control in controls) { - if (control.status == status) return true; - } - return false; + _value = controls.map((control) => control.value).toList(); } @override - bool _allControlsHaveStatus(String status) { - for (var control in controls) { - if (control.status != status) return false; - } - return true; - } - - @override - void _forEachChild(void callback(AbstractControl c)) { - for (var control in controls) { - callback(control); - } - } + bool _anyControlsHaveStatus(String status) => + controls.any((c) => c.status == status); } void _setParentForControls( diff --git a/angular_forms/test/model_test.dart b/angular_forms/test/model_test.dart index a93159a8d6..d9b655d7ea 100644 --- a/angular_forms/test/model_test.dart +++ b/angular_forms/test/model_test.dart @@ -170,41 +170,6 @@ void main() { expect(g.errors, isNull); }); }); - group('disabled', () { - Control control; - ControlGroup group; - - setUp(() { - control = new Control('some value'); - group = new ControlGroup({'one': control}); - }); - - test('should update status', () { - expect(control.disabled, false); - control.markAsDisabled(); - expect(control.disabled, true); - control.markAsEnabled(); - expect(control.disabled, false); - }); - - test('should programatically change value, but not status', () { - expect(control.value, 'some value'); - control.markAsDisabled(); - expect(control.value, 'some value'); - control.updateValue('new value'); - expect(control.value, 'new value', - reason: 'Value changes are propagated when disabled.'); - expect(control.disabled, true); - }); - - test('should update parent', () { - expect(group.disabled, false); - control.markAsDisabled(); - expect(group.disabled, true); - control.markAsEnabled(); - expect(group.disabled, false); - }); - }); }); group('ControlGroup', () { @@ -334,51 +299,6 @@ void main() { expect(g.getError('required', ['invalid']), null); }); }); - - group('disabled', () { - Control control; - ControlGroup group; - - setUp(() { - control = new Control('some value'); - group = new ControlGroup( - {'one': control, 'two': new Control('other value')}); - }); - - test('should update status', () { - expect(group.disabled, false); - group.markAsDisabled(); - expect(group.disabled, true); - group.markAsEnabled(); - expect(group.disabled, false); - }); - - test('should ignore values from disabled children', () { - expect(group.value, {'one': 'some value', 'two': 'other value'}); - control.markAsDisabled(); - expect(group.value, {'two': 'other value'}); - }); - - test('should ignore changes in child values', () { - expect(group.value, {'one': 'some value', 'two': 'other value'}); - group.markAsDisabled(); - expect(group.value, {'one': 'some value', 'two': 'other value'}); - control.updateValue('new value'); - expect(group.disabled, true); - expect(group.value, {'one': 'new value', 'two': 'other value'}, - reason: 'Value changes are propagated when disabled.'); - group.markAsEnabled(); - expect(group.value, {'one': 'new value', 'two': 'other value'}); - }); - - test('should update children', () { - expect(control.disabled, false); - group.markAsDisabled(); - expect(control.disabled, true); - group.markAsEnabled(); - expect(control.disabled, false); - }); - }); }); group('ControlArray', () { @@ -542,50 +462,6 @@ void main() { expect(g.findPath(['array', '0']).value, '111'); }); }); - - group('disabled', () { - Control control; - ControlArray array; - - setUp(() { - control = new Control('some value'); - array = new ControlArray([control, new Control('other value')]); - }); - - test('should update status', () { - expect(array.disabled, false); - array.markAsDisabled(); - expect(array.disabled, true); - array.markAsEnabled(); - expect(array.disabled, false); - }); - - test('should ignore values from disabled children', () { - expect(array.value, ['some value', 'other value']); - control.markAsDisabled(); - expect(array.value, ['other value']); - }); - - test('should ignore changes in child values', () { - expect(array.value, ['some value', 'other value']); - array.markAsDisabled(); - expect(array.value, ['some value', 'other value']); - control.updateValue('new value'); - expect(array.disabled, true); - expect(array.value, ['new value', 'other value'], - reason: 'Value changes are propagated when disabled.'); - array.markAsEnabled(); - expect(array.value, ['new value', 'other value']); - }); - - test('should update children', () { - expect(control.disabled, false); - array.markAsDisabled(); - expect(control.disabled, true); - array.markAsEnabled(); - expect(control.disabled, false); - }); - }); }); }); }