Reactive Forms : Listen changes in ReactiveTextField in flutter?

2.8k views Asked by At

I'm using flutter Reactive Forms and I want to enable/disable a button dynamically while user is editing the textfield. I saw in the Reactive Forms documentation they said like this:

Because of the two-binding capability of the ReactiveTextField with a FormControl the widget don't include properties as controller, validator, autovalidate, onSaved, onChanged, onEditingComplete, onFieldSubmitted, the FormControl is responsible for handling validation as well as changes notifications.

How do I listen changes while user is editing the textfield?

//Text Field
ReactiveFormConsumer(
                    builder: (ctx, form, child) => ReactiveTextField<String>(
                      formControlName: 'name',
                      controller: _nameController,
                      validationMessages: (control) => {
                        ValidationMessage.required: StringConst.namevalnotempty,
                        ValidationMessage.email: StringConst.sfs_incorrectName,
                      },                      
                      onSubmitted: () => form.valid
                          ? _btnState = eButtonState.bActive
                          : _btnState = eButtonState.bDisable,
                      onEditingComplete: () {
                        form.valid
                            ? _btnState = eButtonState.bActive
                            : _btnState = eButtonState.bDisable;
                        FocusScope.of(context).unfocus();
                      },
                      textInputAction: TextInputAction.next,
                      decoration: CommonStyle.textFieldStyle(
                          isFieldValid: form.control('name').valid),
                    ),
                  )


//Save Button
ReactiveFormConsumer(
                    builder: (context, form, child) {
                      return SizedBox(
                        height: 48,
                        width: double.infinity,
                        child: ButtonWidget(
                          eButtonState: _btnState,
                          eButtonType: eButtonType.bText,
                          btnColor: CustomColors.green600,
                          borderColor: CustomColors.green600,
                          textColor: CustomColors.mWhite,
                          text: StringConst.saveChanges,
                          onPressed: () async {
                            var name = form.value["name"].toString();
                            setState(() {
                              _btnState = eButtonState.bLoading;
                            });
                            await editUserProfile(
                              name: name,
                              userType: userType,
                            );
                          },
                        ),
                      );
                    },
                  ),

2

There are 2 answers

0
Minjin Gelegdorj On BEST ANSWER

According to the doc:

If you want to rebuild a widget each time a FormControl value changes you could use the ReactiveValueListenableBuilder widget.

ReactiveValueListenableBuilder will listen to the changes.

ReactiveValueListenableBuilder<double>(
      formControlName: 'name',
      builder: (context, value, child) {
        // depending on the value enable/disable your button
      },
    ),
0
happycoder On

@Minjin helped me to find the answer. I'm posting this for someone else who looking for full answer for the question.

           ReactiveValueListenableBuilder<String>(
                    formControlName: 'name',
                    builder: (context, form, child) {
                      var name = form.value.toString();
                      var initialName = _userModel?.name?.toLowerCase();

                      // depending on the form value enable/disable your 
                      // button, check field is edited
                      if (name != "" && name.toLowerCase() != initialName) {
                        _btnState = eButtonState.bActive;
                      } else {
                        _btnState = eButtonState.bDisable;
                      }
                      
                      return SizedBox(
                        height: 48,
                        width: double.infinity,
                        child: ButtonWidget(
                          eButtonState: _btnState,
                          eButtonType: eButtonType.bText,
                          btnColor: CustomColors.green600,
                          borderColor: CustomColors.green600,
                          textColor: CustomColors.mWhite,
                          text: StringConst.saveChanges,
                          onPressed: () async {
                            
                          },
                        ),
                      );
                    },
                  )