I am trying to create a form page and it contains multiple widgets like FreeTextForm and DropdownButtonFormField. Data for drop down is fetched from sqlite using sqflite
.
The issue happen if I interact with the drop down after I interact with text form, but if I interact with drop down first then go to text form the issue will not appear (it will appear if after interact with text form I interact back with drop down).
Here is the code for the form page
class ActivityFormPage extends StatelessWidget {
const ActivityFormPage({super.key});
@override
Widget build(BuildContext context) {
final ActivityController c = Get.put(
ActivityController(
id: Get.arguments["id"],
db: Get.find<DBInstance>().database,
),
);
return Scaffold(
appBar: AppBar(
leading: IconButton(
onPressed: () => Get.back(),
icon: const Icon(
Icons.arrow_back,
),
),
title: Text(
"New Activity",
textAlign: TextAlign.left,
style: context.textTheme.titleLarge,
),
),
body: SafeArea(
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.all(UIConst.standardPadding * 2),
child: Column(
children: [
Form(
key: c.newActivityKey,
child: Column(
children: [
CustomFreeTextForm(
label: "Title",
hint: "Write activity title",
state: c.state.title,
maxLines: 1,
),
SizedBox(
height: UIConst.standardGapHeight * 2,
),
CustomDropDownForm<CategoryModel>(
label: "Category",
hint: "Select category",
noDataHint: "No category available",
itemArray: c.getAllCategories(),
state: c.state.categoryId,
isDisabled: false,
),
SizedBox(
height: UIConst.standardGapHeight * 2,
),
Obx(() {
return CustomDropDownForm<SubCategoryModel>(
label: "Sub Category",
hint: "Select sub category",
noDataHint: "No sub category available",
itemArray: c.getAllSubCategories(
c.state.categoryId.toInt(),
),
state: c.state.subCategoryId,
isDisabled: c.state.categoryId.toInt() == 0,
);
}),
SizedBox(
height: UIConst.standardGapHeight * 2,
),
Row(
children: [
CustomTimePicker(
width: MediaQuery.of(context).size.width * 0.4,
label: "Start time",
hint: "Select start time",
state: c.state.startTime,
onChange: c.formatDisplayTime,
),
const Expanded(
flex: 1,
child: SizedBox(),
),
CustomTimePicker(
width: MediaQuery.of(context).size.width * 0.4,
label: "End time",
hint: "Select end time",
state: c.state.endTime,
onChange: c.formatDisplayTime,
),
],
),
SizedBox(
height: UIConst.standardGapHeight * 2,
),
CustomFreeTextForm(
label: "Description",
hint: "Write description",
state: c.state.description,
maxLines: 5,
),
],
),
),
],
),
),
),
),
);
}
}
and here is the code of the CustomDropDownForm
class CustomDropDownForm<T extends BaseModel> extends StatelessWidget {
final String label;
final String hint;
final String noDataHint;
final Future<List<T>> itemArray;
final RxInt state;
final bool isDisabled;
const CustomDropDownForm({
super.key,
required this.label,
required this.hint,
required this.noDataHint,
required this.itemArray,
required this.state,
required this.isDisabled,
});
@override
Widget build(BuildContext context) {
return AbsorbPointer(
absorbing: isDisabled,
child: Opacity(
opacity: isDisabled ? 0.5 : 1.0,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
label,
style: context.textTheme.bodySmall,
),
SizedBox(
height: UIConst.standardGapHeight,
),
FutureBuilder<List<T>>(
future: itemArray,
builder: (context, snapshot) {
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
return DropdownButtonFormField<int>(
value: null,
items: snapshot.data!.map((e) {
return DropdownMenuItem(
value: e.id,
child: Text(
e.name,
style: context.textTheme.bodyMedium,
),
);
}).toList(),
onChanged: isDisabled
? null
: (value) {
state.value = value!;
},
hint: Text(
hint,
style: context.textTheme.bodyMedium!.copyWith(
color: state.value == 0 ? Colors.black : Colors.grey,
),
),
decoration: dropDownButtonDecoration,
elevation: 0,
);
} else {
return DropdownButtonFormField(
value: null,
items: const [],
onChanged: null,
hint: Text(noDataHint),
decoration: dropDownButtonDecoration,
);
}
},
),
],
),
),
);
}
}
This is the error looks like
The expectation is that when I interact with the CustomDropDownForm after interact with other widgets, no issue arises and the drop down items are shown
2
Answers
Get.arguments is not null and that it contains the key you’re trying to access. You can do this by performing a null check before accessing the value.
Try below code, it will not crash if the argument is null