@@ -839,7 +839,7 @@ abstract class AbstractControl<T> {
839839
840840/// Tracks the value and validation status of an individual form control.
841841class FormControl <T > extends AbstractControl <T > {
842- final T ? _initialValue ;
842+ T ? _defaultValue ;
843843 final _focusChanges = StreamController <bool >.broadcast ();
844844 FocusController ? _focusController;
845845 bool _hasFocus = false ;
@@ -848,6 +848,13 @@ class FormControl<T> extends AbstractControl<T> {
848848 ///
849849 /// The control can optionally be initialized with a [value] .
850850 ///
851+ /// The [nonNullable] argument is used to determine the state of the control
852+ /// when the [reset] method is called without a value. If [nonNullable] is
853+ /// true (the default), the [reset] method will reset the control to the
854+ /// initial [value] provided in the constructor. If [nonNullable] is false,
855+ /// the [reset] method will reset the control to `null` unless a value is
856+ /// provided.
857+ ///
851858 /// The control can optionally have [validators] that validates
852859 /// the control each time the value changes.
853860 ///
@@ -859,10 +866,6 @@ class FormControl<T> extends AbstractControl<T> {
859866 /// (such as an HTTP request) if the more basic validation methods have
860867 /// already found invalid input.
861868 ///
862- /// You can set an [asyncValidatorsDebounceTime] in millisecond to set
863- /// a delay time before trigger async validators. This is useful for
864- /// minimizing request to a server. The default value is 250 milliseconds.
865- ///
866869 /// You can set [touched] as true to force the validation messages
867870 /// to show up at the very first time the widget that is bound to this
868871 /// control builds in the UI.
@@ -876,6 +879,7 @@ class FormControl<T> extends AbstractControl<T> {
876879 ///
877880 FormControl ({
878881 T ? value,
882+ bool nonNullable = true ,
879883 super .validators,
880884 super .asyncValidators,
881885 @Deprecated (
@@ -887,14 +891,24 @@ class FormControl<T> extends AbstractControl<T> {
887891 super .asyncValidatorsDebounceTime,
888892 super .touched,
889893 super .disabled,
890- }) : _initialValue = value {
894+ }) : _defaultValue = nonNullable ? value : null {
891895 if (value != null ) {
892896 this .value = value;
893897 } else {
894898 updateValueAndValidity ();
895899 }
896900 }
897901
902+ /// Gets the default value of the control.
903+ ///
904+ /// This value is determined by the [value] and [nonNullable] arguments
905+ /// passed to the constructor:
906+ /// - If [nonNullable] is `true` (the default), this holds the initial [value] .
907+ /// - If [nonNullable] is `false` , this is `null` .
908+ ///
909+ /// When [reset] is called without a value, the control resets to this value.
910+ T ? get defaultValue => _defaultValue;
911+
898912 /// True if the control is marked as focused.
899913 bool get hasFocus => _hasFocus;
900914
@@ -1016,21 +1030,92 @@ class FormControl<T> extends AbstractControl<T> {
10161030 }
10171031 }
10181032
1033+ /// Resets the form control, marking it as untouched and pristine.
1034+ ///
1035+ /// If [value] is provided, the control is reset to that value.
1036+ ///
1037+ /// If [value] is not provided (null), the behavior depends on the [nonNullable]
1038+ /// argument passed to the constructor:
1039+ /// - If [nonNullable] is `true` (the default), the control resets to the
1040+ /// initial value provided in the constructor.
1041+ /// - If [nonNullable] is `false` , the control resets to `null` .
1042+ ///
1043+ /// If [overwriteDefaultValue] is true, then the value used to reset the
1044+ /// control becomes the new default value of the control.
1045+ ///
1046+ /// The argument [disabled] is optional and resets the disabled status of the
1047+ /// control. If value is `true` then it will disable the control, if value is
1048+ /// `false` then it will enable the control, and if the value is `null` or
1049+ /// not set (the default) then the control will state in the same state that
1050+ /// it previously was.
1051+ ///
1052+ /// The argument [removeFocus] is optional and remove the UI focus from the
1053+ /// control.
1054+ ///
1055+ /// When [updateParent] is true or not supplied (the default) each change
1056+ /// affects this control and its parent, otherwise only affects to this
1057+ /// control.
1058+ ///
1059+ /// When [emitEvent] is true or not supplied (the default), both the
1060+ /// *statusChanges* and *valueChanges* events notify listeners with the
1061+ /// latest status and value when the control is reset. When false, no events
1062+ /// are emitted.
1063+ ///
1064+ /// ### Examples
1065+ ///
1066+ /// **Reset to a specific value**
1067+ /// ```dart
1068+ /// final control = FormControl<String>();
1069+ ///
1070+ /// control.reset(value: 'John Doe');
1071+ ///
1072+ /// print(control.value); // output: 'John Doe'
1073+ /// ```
1074+ ///
1075+ /// **Reset to initial value (nonNullable: true)**
1076+ /// ```dart
1077+ /// // nonNullable is true by default
1078+ /// final control = FormControl<String>(value: 'Initial Value');
1079+ ///
1080+ /// control.value = 'New Value';
1081+ ///
1082+ /// // Resets to 'Initial Value' because no value was provided
1083+ /// // and nonNullable is true.
1084+ /// control.reset();
1085+ ///
1086+ /// print(control.value); // output: 'Initial Value'
1087+ /// ```
1088+ ///
1089+ /// **Reset to null (nonNullable: false)**
1090+ /// ```dart
1091+ /// final control = FormControl<String>(
1092+ /// value: 'Initial Value',
1093+ /// nonNullable: false,
1094+ /// );
1095+ ///
1096+ /// control.value = 'New Value';
1097+ ///
1098+ /// // Resets to null because no value was provided
1099+ /// // and nonNullable is false.
1100+ /// control.reset();
1101+ ///
1102+ /// print(control.value); // output: null
1103+ ///
10191104 @override
10201105 void reset ({
10211106 T ? value,
1107+ bool overwriteDefaultValue = false ,
10221108 bool updateParent = true ,
10231109 bool emitEvent = true ,
10241110 bool removeFocus = false ,
10251111 bool ? disabled,
10261112 }) {
1027- // If `value` is null, it implies either `reset()` was called (no explicit value)
1028- // or `reset(value: null)` was called.
1029- // In line with "If no value is provided it should assign the initial value",
1030- // we use `_initialValue` when `value` is `null`.
1031- // If `value` is explicitly provided and not null, we use that.
1113+ if (overwriteDefaultValue) {
1114+ _defaultValue = value;
1115+ }
1116+
10321117 super .reset (
1033- value: value ?? _initialValue ,
1118+ value: value ?? _defaultValue ,
10341119 updateParent: updateParent,
10351120 emitEvent: emitEvent,
10361121 removeFocus: removeFocus,
0 commit comments