我正在使用表格。而且,我需要关注有错误的节点。目前,有 3 个字段是必需的。FullName
, DoB
, 和Card Number
. 其他字段已经有初始值,所以不需要验证它们。
我想关注有错误的节点。下面的代码在使用验证时_personalDetailsFormKey.currentState!.validate()
将运行每个字段的 validate 方法并专注于该字段。
错误:上述方法适用于一个错误。由于所有节点都在验证时获得焦点,当所有字段为空并且使用某个提交按钮执行以上验证时,cardValueField
接收焦点。当我在 上写下至少一个值时cardValueField
,我会立即dobField
选择日期。而且,一旦选择了日期,我就会被带去fullNameField
填写文本。
我想知道是否有可能只关注第一个有错误的字段,因为当没有给出错误时,上述方法作为验证器不可行,会弹出焦点堆栈并转到堆栈上的下一项。
Step _personalDetailStep(BuildContext context) {
final fullName = ref.watch(membershipOrSupportFormStateProvider).fullName;
print(Localizations.localeOf(context).languageCode);
return Step(
title: Text(AppLocalizations.of(context)!.personalDetails),
state: ref.watch(membershipOrSupportFormStateProvider).stepStates[0],
content: FormBuilder(
key: _personalDetailsFormKey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: Column(
children: [
FormBuilderTextField(
name: AppStrings.fullNameKey,
controller: _fullNameTextFormFieldController,
decoration: InputDecoration(
labelText: AppLocalizations.of(context)!.fullNameLabel),
key: const Key(AppStrings.fullNameKey),
textInputAction: TextInputAction.next,
focusNode: _fullNameFocusNode,
validator: (value) {
var requiredValidator = FormBuilderValidators.required<String>(
context,
errorText:
AppLocalizations.of(context)!.fullNameEmptyErrorText);
var result = requiredValidator(value);
if (result != null) {
_fullNameFocusNode.requestFocus();
}
return result;
},
autovalidateMode: AutovalidateMode.onUserInteraction,
onChanged: (value) {
if (value != null) {
if (value.isNotEmpty) {
ref.read(membershipOrSupportFormStateProvider).fullName =
value;
ref
.read(membershipOrSupportFormStateProvider.notifier)
.notifyStateUpdate();
}
}
},
),
FormBuilderDateTimePicker(
controller: _dateOfBirthTextFormFieldController,
textInputAction: TextInputAction.next,
focusNode: _dateOfBirthFocusNode,
initialDate: DateTime.fromMillisecondsSinceEpoch(0),
lastDate: DateTime(
DateTime.now().year - 18,
DateTime.now().month,
DateTime.now().day - 1,
),
format: DateFormat.yMMMd(
Localizations.localeOf(context).languageCode),
name: AppStrings.dateOfBirthKey,
inputType: InputType.date,
decoration: InputDecoration(
labelText: AppLocalizations.of(context)!.dateOfBirthLabel,
),
validator: FormBuilderValidators.required(
context,
errorText: AppLocalizations.of(context)!
.dateOfBirthRequiredErrorText),
onChanged: (value) {
if (value != null) {
ref.read(membershipOrSupportFormStateProvider).birthDate =
value;
ref
.read(membershipOrSupportFormStateProvider.notifier)
.notifyStateUpdate();
}
},
),
FormBuilderRadioGroup(
name: AppStrings.genderKey,
initialValue: Gender.male,
decoration: InputDecoration(
labelText: AppLocalizations.of(context)!.genderLabel,
),
orientation: OptionsOrientation.vertical,
options: [
FormBuilderFieldOption(
value: Gender.male,
child: Text(AppLocalizations.of(context)!.genderMaleText)),
FormBuilderFieldOption(
value: Gender.female,
child:
Text(AppLocalizations.of(context)!.genderFemaleText)),
FormBuilderFieldOption(
value: Gender.other,
child: Text(AppLocalizations.of(context)!.genderOtherText)),
],
onChanged: (gender) {
print('Gender: ' + gender.toString());
},
),
FormBuilderRadioGroup(
name: AppStrings.disabilityKey,
initialValue: Disability.no,
decoration: InputDecoration(
labelText: AppLocalizations.of(context)!.disabilityLabel,
),
orientation: OptionsOrientation.vertical,
options: [
FormBuilderFieldOption(
value: Disability.yes,
child: Text(AppLocalizations.of(context)!.yesText),
),
FormBuilderFieldOption(
value: Disability.no,
child: Text(AppLocalizations.of(context)!.noText)),
],
onChanged: (disability) {
print("Disability: " + disability.toString());
},
),
FormBuilderDropdown(
name: AppStrings.identityCardTypeKey,
initialValue: IdentityCard.citizenship,
decoration: InputDecoration(
labelText: AppLocalizations.of(context)!.identityCardTypeLabel,
),
items: [
DropdownMenuItem(
value: IdentityCard.citizenship,
child: Text(AppLocalizations.of(context)!.citizenshipText),
),
DropdownMenuItem(
value: IdentityCard.votingCard,
child: Text(AppLocalizations.of(context)!.votingCardText),
),
DropdownMenuItem(
value: IdentityCard.passport,
child: Text(AppLocalizations.of(context)!.passportText),
),
DropdownMenuItem(
value: IdentityCard.drivingLicense,
child: Text(AppLocalizations.of(context)!.drivingLicenseText),
),
],
onChanged: (card) {
print('Identity Card Type: ' + card.toString());
},
),
FormBuilderTextField(
name: AppStrings.identityCardValueKey,
controller: _identityCardController,
focusNode: _identityCardValueFocusNode,
textInputAction: TextInputAction.done,
decoration: InputDecoration(
labelText: AppLocalizations.of(context)!.cardNumberText),
validator: (value) {
var requiredValidator = FormBuilderValidators.required(context,
errorText: AppLocalizations.of(context)!
.identityCardRequiredErrorText);
var result = requiredValidator(value);
if (result != null) {
_identityCardValueFocusNode.requestFocus();
}
return result;
},
onSubmitted: (value) {
print('Card number: ' + value.toString());
},
),
],
),
),
);
}