簡體   English   中英

是否可以在帶有 GetX 的無狀態小部件中使用“formKey.currentState”?

[英]Is it possible to use "formKey.currentState" inside a stateless widget with GetX?

我正在嘗試將使用提供程序 package 和有狀態小部件的代碼轉換為使用 GetX package 和無狀態小部件。 我確實遇到的一個問題是我有一個使用 animation 更改的表單(從登錄到注冊,反之亦然),但是當我檢查下一行的結果時if (._formKey.currentState!.validate())似乎不起作用。

這是相關代碼:

auth_controller.dart:

enum AuthMode { Signup, Login }

class AuthController extends GetxController with GetSingleTickerProviderStateMixin  {
  static AuthController instance = Get.find();
  Rx<dynamic>? authMode = AuthMode.Login.obs;
  RxBool? isLoading = false.obs;
  String? _token; 
  DateTime? _expiryDate;
  String? _userId;
  Timer? _authTimer;
final _isAuth = false.obs;


  AnimationController? controller;
  Animation<Offset>? slideAnimation;
  Animation<double>? opacityAnimation;

    @override
  void onInit() {
    super.onInit();
    controller = AnimationController(
      vsync: this,
      duration: const Duration(
        milliseconds: 300,
      ),
    );
    slideAnimation = Tween<Offset>(
      begin: const Offset(0, -1.5),
      end: const Offset(0, 0),
    ).animate(
      CurvedAnimation(
        parent: controller as Animation<double>,
        curve: Curves.fastOutSlowIn,
      ),
    );
    opacityAnimation = Tween(begin: 0.0, end: 1.0).animate(
      CurvedAnimation(
        parent: controller as Animation<double>,
        curve: Curves.easeIn,
      ),
    );
    // _heightAnimation.addListener(() => setState(() {}));
  }
.
.
.

auth_screen.dart:

return Card(
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(10.0),
      ),
      elevation: 8.0,
      child: AnimatedContainer(
        duration: const Duration(milliseconds: 300),
        curve: Curves.easeIn,
        height: _authMode!.value == AuthMode.Signup ? 320 : 260,
        //height: _heightAnimation.value.height,
        constraints: BoxConstraints(
            minHeight: _authMode.value == AuthMode.Signup ? 320 : 260),
        width: deviceSize.width * 0.75,
        padding: const EdgeInsets.all(16.0),
        child: Obx(() => Form(
              key: _formKey,
              child: SingleChildScrollView(
                child: Column(
                  children: <Widget>[
                    TextFormField(
                      decoration: const InputDecoration(labelText: 'E-Mail'),
                      keyboardType: TextInputType.emailAddress,
                      validator: (value) {
                        if (value!.isEmpty || !value.contains('@')) {
                          return 'Invalid email!';
                        }
                      },
                      onSaved: (value) {
                        _authData['email'] = value as String;
                      },
                    ),
                    TextFormField(
                      decoration: const InputDecoration(labelText: 'Password'),
                      obscureText: true,
                      controller: _passwordController,
                      validator: (value) {
                        if (value!.isEmpty || value.length < 5) {
                          return 'Password is too short!';
                        }
                      },
                      onSaved: (value) {
                        _authData['password'] = value as String;
                      },
                    ),
                    AnimatedContainer(
                      constraints: BoxConstraints(
                        minHeight: _authMode.value == AuthMode.Signup ? 60 : 0,
                        maxHeight: _authMode.value == AuthMode.Signup ? 120 : 0,
                      ),
                      duration: const Duration(milliseconds: 300),
                      curve: Curves.easeIn,
                      child: FadeTransition(
                        opacity: _opacityAnimation as Animation<double>,
                        child: SlideTransition(
                          position: _slideAnimation as Animation<Offset>,
                          child: TextFormField(
                            enabled: _authMode.value == AuthMode.Signup,
                            decoration: const InputDecoration(
                                labelText: 'Confirm Password'),
                            obscureText: true,
                            validator: _authMode.value == AuthMode.Signup
                                ? (value) {
                                    if (value != _passwordController.text) {
                                      return 'Passwords do not match!';
                                    }
                                  }
                                : null,
                          ),
                        ),
                      ),
                    ),
                    const SizedBox(
                      height: 20,
                    ),
                    if (_isLoading!.value)
                      const CircularProgressIndicator()
                    else
                      ElevatedButton(
                            child:  Text(_authMode.value == AuthMode.Login
                                ? 'LOGIN'
                                : 'SIGN UP'),
                            onPressed: _submit,
                            style: ElevatedButton.styleFrom(
                              shape: RoundedRectangleBorder(
                                borderRadius: BorderRadius.circular(30),
                              ),
                              primary: Theme.of(context).primaryColor,
                              padding: const EdgeInsets.symmetric(
                                  horizontal: 30.0, vertical: 8.0),
                              onPrimary: Theme.of(context)
                                  .primaryTextTheme
                                  .button!
                                  .color,
                            ),
                          ),
                     TextButton(
                          child: Text(
                              '${_authMode.value == AuthMode.Login ? 'SIGNUP' : 'LOGIN'} '),
                          onPressed: _switchAuthMode,
                          style: TextButton.styleFrom(
                            padding: const EdgeInsets.symmetric(
                                horizontal: 30.0, vertical: 4),
                            tapTargetSize: MaterialTapTargetSize.shrinkWrap,
                            textStyle: TextStyle(
                                color: Theme.of(context).primaryColor),
                          ),
                        ),
                  ],
                ),
              ),
            )),
      ),
    );

我不知道問題出在哪里以及如何以正確的方式轉換代碼? 我也不知道是否有可能?

是的,您可以將 FormState 與 GetX 控制器和無狀態小部件一起使用,但是您需要在 controller 中實例化 GlobalKey,然后確保 controller 在 UI 上“放置”以供使用。

class YourController extends GetXController {
  final formKey = GlobalKey<FormState>();
}

然后將 controller 作為依賴項注入到無狀態小部件中

class YourWidget extends StatelessWidget {
   final getxController = Get.put(YourController());
}

然后將其添加到您的表單小部件

    child: Form(
      key: getxController.formKey,

將所需的驗證函數添加到 controller 和 TextInput 小部件后,您可以從 Getx 擴展中調用 formKey.Validate() controller class

 void submitForm() {
    final isValid = formKey.currentState.validate();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM