You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Formz实现表单验证遇类型不匹配及属性未定义错误求助

解决Formz表单验证的两个错误

错误1:bool无法赋值给FormzSubmissionStatus?

问题核心是Formz.validate()返回布尔值(验证通过为true,否则为false),但state.copyWith的status参数要求的是FormzSubmissionStatus枚举类型,两者类型不兼容。FormzSubmissionStatus的作用是跟踪表单提交流程状态(初始、正在提交、成功、失败),而非实时验证结果,不能混用。

修复方案

在SignUpState中添加计算属性来判断表单整体有效性,字段更新时仅修改对应字段,不改动status:

修改SignUpState类:

class SignUpState extends Equatable {
  // 原有代码不变

  // 添加计算属性,判断所有字段是否验证通过
  bool get isValid => Formz.validate([name, email, password]);

  @override
  List<Object> get props => [name, email, password, status];
}

修改SignupController的onNameChange方法:

void onNameChange(String value) {
  final name = Name.dirty(value);
  state = state.copyWith(
    name: name,
    // 移除原有的status赋值,避免类型不匹配
  );
}

错误2:FormzSubmissionStatus没有isValidated getter

FormzSubmissionStatus仅包含提交状态的枚举值,不存在isValidated属性。判断表单是否可提交,需要直接通过字段的验证结果来判断。

修复方案

用SignUpState新增的isValid计算属性判断表单有效性,同时在提交时正确管理提交状态:

修改signUpWithEmailAndPassword方法:

void signUpWithEmailAndPassword() async {
  // 先校验表单是否有效
  if (!state.isValid) return;

  // 设置提交中状态
  state = state.copyWith(status: FormzSubmissionStatus.inProgress);

  try {
    // 执行实际注册逻辑(此处替换为API调用)
    print('Signing up...');
    // 注册成功后更新状态
    state = state.copyWith(status: FormzSubmissionStatus.success);
  } catch (e) {
    // 注册失败时保存错误信息并更新状态
    state = state.copyWith(
      status: FormzSubmissionStatus.failure,
      errorMessage: e.toString(),
    );
  }
}

完整修改后的代码

SignupController

import 'package:flymedia_app/src/auth/signup/controller/signup_state.dart';
import 'package:form_validators/form_validators.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

class SignupController extends StateNotifier<SignUpState> {
  SignupController() : super(const SignUpState());

  void onNameChange(String value) {
    final name = Name.dirty(value);
    state = state.copyWith(name: name);
  }

  void onEmailChange(String value) {
    final email = Email.dirty(value);
    state = state.copyWith(email: email);
  }

  void onPasswordChange(String value) {
    final password = Password.dirty(value);
    state = state.copyWith(password: password);
  }

  void signUpWithEmailAndPassword() async {
    if (!state.isValid) return;

    state = state.copyWith(status: FormzSubmissionStatus.inProgress);

    try {
      print('Signing up...');
      // 替换为实际注册API调用
      state = state.copyWith(status: FormzSubmissionStatus.success);
    } catch (e) {
      state = state.copyWith(
        status: FormzSubmissionStatus.failure,
        errorMessage: e.toString(),
      );
    }
  }
}

SignUpState

import 'package:equatable/equatable.dart';
import 'package:form_validators/form_validators.dart';

class SignUpState extends Equatable {
  final Name name;
  final Email email;
  final Password password;
  final FormzSubmissionStatus status;
  final String? errorMessage;

  const SignUpState({
    this.name = const Name.pure(),
    this.email = const Email.pure(),
    this.password = const Password.pure(),
    this.status = FormzSubmissionStatus.initial,
    this.errorMessage,
  });

  SignUpState copyWith({
    Name? name,
    Email? email,
    Password? password,
    FormzSubmissionStatus? status,
    String? errorMessage,
  }) {
    return SignUpState(
      name: name ?? this.name,
      email: email ?? this.email,
      password: password ?? this.password,
      status: status ?? this.status,
      errorMessage: errorMessage ?? this.errorMessage,
    );
  }

  bool get isValid => Formz.validate([name, email, password]);

  @override
  List<Object> get props => [name, email, password, status];
}

内容的提问来源于stack exchange,提问作者Jesse Josiah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 23:11:36