Flutter语言 - DropdownButton selectedValue在controller.dart中返回nul



我有一个状态的dropdownButton,当值被选中时,控制器页面返回null。我如何得到这个值?

class StatesFieldWidget extends StatefulWidget with BaseField {
late final MacroFieldDto _macroField;
StatesFieldWidget({
required MacroFieldDto macroField,
required double fontSize,
done = false
}) : super(key: Key(macroField.uiCode)) {
this.fontSize = fontSize;
_macroField = macroField;
}
@override
_StatesFieldWidgetState createState() {
return _StatesFieldWidgetState();
}
@override
MacroFieldDto? get value {
return _macroField;
}
@override
bool get valid {
return value!.valid;
}
}
class _StatesFieldWidgetState extends State<StatesFieldWidget> {


String? selectedValue;
String get value {


if(selectedValue == null){
log(selectedValue.toString());
return "NU";
} else{
log(selectedValue.toString());
return selectedValue.toString();

}
}

@override
Widget build(BuildContext context) {
return FieldContainerWidget.fieldContainer(
Container(
margin: const EdgeInsets.all(2),
//padding: EdgeInsets.only(top: 5, bottom: 5, right: 5, left: 5),
padding: const EdgeInsets.only(right: 5, left: 5),
color: Colors.white,
child: DropdownButton<String>(
value: selectedValue,
icon: const Icon(
Icons.arrow_downward,
key: Key('btn_expand_states'),
),
iconSize: 24,
elevation: 16,
style: TextStyle(
color: Colors.black87,
fontSize: widget.fontSize,
),
underline: Container(
height: 0,
color: Colors.transparent,
),
onChanged: (String? newValue) async {
setState(() {
selectedValue = newValue;
});
// log(selectedValue.toString());
},
items: states().map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
),
);
}
// TODO: verify behaviour for other languages;
List<String> states() {
final states = <String>[];
states.add("AC");
states.add("AL");
states.add("AP");
states.add("AM");
states.add("BA");
states.add("CE");
states.add("DF");
states.add("ES");
states.add("GO");
states.add("MA");
states.add("MT");
states.add("MS");
states.add("MG");
states.add("PA");
states.add("PB");
states.add("PR");
states.add("PE");
states.add("PI");
states.add("RJ");
states.add("RN");
states.add("RS");
states.add("RO");
states.add("RR");
states.add("SC");
states.add("SP");
states.add("SE");
states.add("TO");
return states;
}



}

controller.dart

class MessageSendController = _MessageSendControllerBase with _$MessageSendController;
abstract class _MessageSendControllerBase with Store {
final txtSearchCtl = TextEditingController();
GlobalKey<FormState> formKey = GlobalKey<FormState>();
GlobalKey<SendMessageAnimationTabletWidgetState>? sendAnimationTabletState;
GlobalKey<SendMessageAnimationPhoneWidgetState>? sendAnimationPhoneState;
final OdometerService _odometerService = IoC.get<OdometerService>()!;
final AuthStatusService _authStatusService = IoC.get<AuthStatusService>()!;
final MessageListController _messageListController = IoC.get<MessageListController>()!;
String _odometerValue = '';
String _driverIdValue = '';
final MessageService _messageService = MessageService();
bool? isMessageFromOperationCycle = false;
bool isModalMessageOpen = false;
@observable
List<Macro> macros = [];
@observable
Macro selectedMacro = Macro();
@observable
List<BaseField> baseFields = [];
@observable
Widget? selectedMacroContainer;
@observable
bool isVisibleBtnImportant = true;
@observable
bool isVisibleBtnNormal = true;
@action
Future loadFields() async {
double fontSize = _fontSize;
baseFields = [];
List<Row> rows = [];
List<Widget> actualRow = [];
int columnsCount = 0;
for (var macroField in selectedMacro.fields) {
if (macroField.macroFieldType == MacroFieldType.lineBreak || columnsCount >= 38) {
rows.add(Row(children: actualRow));
actualRow = [];
columnsCount = 0;
continue;
}
columnsCount += macroField.size!;
actualRow.add(_getFieldWidget(macroField, fontSize));
if (selectedMacro.fields.length > 15) {
await Future.delayed(const Duration(milliseconds: 10));
}
}
rows.add(Row(children: actualRow));
selectedMacroContainer = Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: rows,
);
}
@action
loadData() async {
isModalMessageOpen = true;
formKey = GlobalKey<FormState>();
await treatLoadFields();
}
Future treatLoadFields() async {
if (selectedMacro.formNumber >= 0) {
await loadFields();
await Future.delayed(const Duration(milliseconds: 100));
if (selectedMacro.formNumber > 0) {
txtSearchCtl.text = "Formulário ${selectedMacro.formNumber.toString()}";
} else {
txtSearchCtl.text = "lbl_free_text".translate;
}
}
}
@action
Future getHodometerAndDriverId(List<Macro> macroList) async {
if (macroList.any((element) => element.fields.any((c) => c.macroFieldType == MacroFieldType.odometerAutomatic))) {
_odometerValue = await _getOdometer();
}
if (macroList.any((element) => element.fields.any((c) => c.macroFieldType == MacroFieldType.driverId))) {
_driverIdValue = await _getDriverId();
}
}
@action
String formatMacroName(Macro macro) {
if (selectedMacro.formNumber < 0) return "";
if (macro.formNumber == selectedMacro.formNumber) return "";
if (macro.formNumber > 0) {
return "Formulário ${macro.formNumber}";
} else {
return "Texto Livre";
}
}
@action
List<String>? getMacroNumberList() {
if (macros.isEmpty) return null;
List<String> list = [];
for (var f in macros) {
list.add(f.formNumber.toString());
}
return list;
}
@action
Macro getMacroByFormNumber(int formNumber) {
return macros.firstWhere((m) => m.formNumber == formNumber);
}
@action
clearFormFields(BuildContext context) {
Dialogterminalmovel.showConfirm(
context: context,
content: 'msg095'.translate,
callbackYes: () {
loadFields();
},
);
}
@action
void macroNameChange(String newValue) {
int? macroNumber = int.tryParse(newValue);
Macro macro;
if (macroNumber != null) {
macro = macros.where((m) => m.formNumber == macroNumber).first;
} else {
macro = macros.where((m) => m.formNumber == 0).first;
}
selectedMacro = macro;
loadFields();
}
@action
Future<Message?> sendNormal(BuildContext context) async {
return await _send(MessageTypePriority.normal, context, 0);
}
@action
Future<Message?> sendImportant(BuildContext context) async {
return await _send(MessageTypePriority.important, context, 0);
}
@action
Future<Message?> sendNormalReply(BuildContext context, Message messageReply) async {
return await _send(MessageTypePriority.normal, context, messageReply.messageUccId);
}
@action
Future<Message?> sendImportantReply(BuildContext context, Message messageReply) async {
return await _send(MessageTypePriority.important, context, messageReply.messageUccId);
}
Future<Message?> _send(int priority, BuildContext context, int? idMessageReply) async {
try {
isVisibleBtnImportant = false;
isVisibleBtnNormal = false;
if (formKey.currentState!.validate() == false) {
isVisibleBtnImportant = true;
isVisibleBtnNormal = true;
return null;
}
final fields = baseFields.map((f) => f.value).whereNotNull().toList();
//log(fields[1].value.toString());
// final fieldz = fields.map((e) => e).toString();
Message sendMessage;
if (idMessageReply != null && idMessageReply > 0) {
sendMessage = Message.send(
fields: fields,
priority: priority,
macro: selectedMacro,
idMessageReply: idMessageReply,
);
} else {
sendMessage = Message.send(
fields: fields,
priority: priority,
macro: selectedMacro,
);
}
if (sendMessage.body == "_" && sendMessage.formNumber == 0) {
Dialogterminalmovel.showOk(
context: context,
content: 'msg098'.translate,
callback: () {
isVisibleBtnImportant = true;
isVisibleBtnNormal = true;
},
);
return null;
}
if (sendMessage.body == "_" && sendMessage.formNumber > 0) {
Dialogterminalmovel.showOk(
context: context,
content: 'null',
callback: () {
isVisibleBtnImportant = true;
isVisibleBtnNormal = true;
},
);
return null;
}
if (isMessageFromOperationCycle != true) {
bool result = await _messageService.sendMessage(sendMessage);
if (!result) {
Dialogterminalmovel.showOk(
context: context,
content: 'msg002'.translate,
callback: () {
isVisibleBtnImportant = true;
isVisibleBtnNormal = true;
},
);
return null;
}
}
await _messageListController.refresh(0);
await _messageListController.refresh(1);
if (DeviceType.get().isTablet!) {
await sendAnimationTabletState!.currentState!.run();
} else {
await sendAnimationPhoneState!.currentState!.run();
}
isVisibleBtnImportant = true;
isVisibleBtnNormal = true;
isModalMessageOpen = false;
return sendMessage;
} catch (e) {
isVisibleBtnImportant = true;
isVisibleBtnNormal = true;
return null;
}
}
_getFieldWidget(MacroFieldDto macroField, double fontSize) {
Widget? fieldWidget = Column();
dynamic field;
try {
if (macroField.macroFieldType == MacroFieldType.alphabetical) {
field = AlphabeticalFieldWidget(macroField: macroField, fontSize: fontSize);
} else if (macroField.macroFieldType == MacroFieldType.alphanumeric) {
field = AlphanumericFieldWidget(macroField: macroField, fontSize: fontSize);
} else if (macroField.macroFieldType == MacroFieldType.zipCode) {
field = ZipCodeFieldWidget(macroField: macroField, fontSize: fontSize);
} else if (macroField.macroFieldType == MacroFieldType.cpf) {
field = CpfFieldWidget(macroField: macroField, fontSize: fontSize);
} else if (macroField.macroFieldType == MacroFieldType.date) {
field = DateFieldWidget(macroField: macroField, fontSize: fontSize);
} else if (macroField.macroFieldType == MacroFieldType.dateComplete) {
field = DateCompleteFieldWidget(macroField: macroField, fontSize: fontSize);
} else if (macroField.macroFieldType == MacroFieldType.daysOfWeek) {
field = DaysOfWeekFieldWidget(macroField: macroField, fontSize: fontSize);
} else if (macroField.macroFieldType == MacroFieldType.states) {
field = StatesFieldWidget(macroField: macroField, fontSize: fontSize);
} else if (macroField.macroFieldType == MacroFieldType.rangeOfIntegers) {
field = RangeOfIntegersFieldWidget(macroField: macroField, fontSize: fontSize);
} else if (macroField.macroFieldType == MacroFieldType.intWithSignal) {
field = IntWithSignalFieldWidget(macroField: macroField, fontSize: fontSize);
} else if (macroField.macroFieldType == MacroFieldType.intComplete) {
field = IntCompleteFieldWidget(macroField: macroField, fontSize: fontSize);
} else if (macroField.macroFieldType == MacroFieldType.intWithoutSignal) {
field = IntWithoutSignalFieldWidget(macroField: macroField, fontSize: fontSize);
} else if (macroField.macroFieldType == MacroFieldType.list) {
field = ListFieldWidget(macroField: macroField, fontSize: fontSize);
} else if (macroField.macroFieldType == MacroFieldType.free) {
field = FreeFieldWidget(macroField: macroField, fontSize: fontSize);
} else if (macroField.macroFieldType == MacroFieldType.month) {
field = MonthFieldWidget(macroField: macroField, fontSize: fontSize);
} else if (macroField.macroFieldType == MacroFieldType.currency) {
field = CurrencyFieldWidget(macroField: macroField, fontSize: fontSize);
} else if (macroField.macroFieldType == MacroFieldType.real) {
field = RealFieldWidget(macroField: macroField, fontSize: fontSize);
} else if (macroField.macroFieldType == MacroFieldType.label) {
field = LabelFieldWidget(macroField: macroField, fontSize: fontSize);
} else if (macroField.macroFieldType == MacroFieldType.password) {
field = PasswordFieldWidget(macroField: macroField, fontSize: fontSize);
} else if (macroField.macroFieldType == MacroFieldType.yesNo) {
field = YesNoFieldWidget(macroField: macroField, fontSize: fontSize);
} else if (macroField.macroFieldType == MacroFieldType.phone) {
field = PhoneFieldWidget(macroField: macroField, fontSize: fontSize);
} else if (macroField.macroFieldType == MacroFieldType.phoneWithDDD) {
field = PhoneWithDDDFieldWidget(macroField: macroField, fontSize: fontSize);
} else if (macroField.macroFieldType == MacroFieldType.time12H) {
field = Time12hFieldWidget(macroField: macroField, fontSize: fontSize);
} else if (macroField.macroFieldType == MacroFieldType.time24H) {
field = Time24hFieldWidget(macroField: macroField, fontSize: fontSize);
} else if (macroField.macroFieldType == MacroFieldType.odometerAutomatic) {
macroField.value = _odometerValue;
field = OdometerFieldWidget(macroField: macroField, fontSize: fontSize);
} else if (macroField.macroFieldType == MacroFieldType.driverId) {
macroField.value = _driverIdValue;
field = DriverIdFieldWidget(macroField: macroField, fontSize: fontSize);
} else if (macroField.macroFieldType == MacroFieldType.freeText) {
field = FreeTextFieldWidget(macroField: macroField, fontSize: fontSize);
} else if (macroField.macroFieldType == MacroFieldType.hourOfMessage) {
var dateTime = DateTime.now().timeStamp.toString();
macroField.value = dateTime;
field = HourOfMessageFieldWidget(macroField: macroField, fontSize: fontSize);
}
} catch (ex) {
field = const Text("");
}
//log(field.toString());
fieldWidget = field;
baseFields.add(field);
return fieldWidget;
}
_getOdometer() async {
final odometer = await _odometerService.syncData();
final odometerValue = odometer!.odometer.toStringAsFixed(2);
return odometerValue;
}
_getDriverId() async {
final authStatus = await _authStatusService.syncData();
final driverId = authStatus != null && authStatus.driverId > 0 ? authStatus.driverId.toString() : '';
return driverId;
}
double get _fontSize => DeviceType.get().isTablet! ? 30 : 14;
}

函数String get值不工作,日志不显示。字段返回null。我想知道它是格式化还是字符串化字段,因为.map()不会解析它,因为结果是作为StatesWidget的实例出现的。

将文件相加以指出处理值的位置。创建了一个类MacroFieldDto来初始化这个值。

abstract class MacroFieldDto {
int? size;
bool? isRequired;
String? param;
int? macroFieldType;
String? value;
List<String> notifications = <String>[];
String get uiCode => DateTime.now().millisecondsSinceEpoch.toString();
MacroFieldDto({
this.size,
this.isRequired,
this.param,
this.macroFieldType,
});
void inputTextIsValid();
void setValueFromUccFormat(String value) => this.value = value;
String? get valueToUccFormat => value;
String? get formatedValue => value;
bool get valid {
notifications = <String>[];
if (macroFieldType == MacroFieldType.label) {
inputTextIsValid();
return notifications.isEmpty;
}
_treatRequireValueIsValid();
if (value != null && value!.isNotEmpty) {
inputTextIsValid();
_validateSize();
}
return notifications.isEmpty;
}
_treatRequireValueIsValid() {
if (isRequired! && (value == null || value!.isEmpty)) {
notifications.add("msg004");
}
}
_validateSize() {
if (value!.length > size!) notifications.add("msg006");
}
}

在statesfieldto中验证输入:

class StatesFieldDto extends MacroFieldDto {
final String regexValidation = r'^[A-Z]{2}$';
StatesFieldDto({int? size, bool? isRequired})
: super(size: size, isRequired: isRequired) {
macroFieldType = MacroFieldType.states;
}
@override
void inputTextIsValid() {
final regex = RegExp(regexValidation);
if (regex.hasMatch(value!) == false) notifications.add("msg006");
}
@override
void setValueFromUccFormat(String value) {
this.value = value;
}
}

我已经设法通过setState设置值(来自评论)。但也可以通过验证器进行设置。

onChanged: (salutation) =>
setState(() => selectedSalutation = salutation),
validator: (value) => value == null ? 'field required' : null,

最新更新