I am calling form below for add and edit operations.When clicked on edit button I have to get details of particular document based on its unique Id, so when clicked on edit I am calling API in initState() but when clicked on add button I am facing an issue like futureDocuments is not initialised, I cannot initialise it to null also, how to resolve this?
I am also getting an error like dId is not initialised while cliked on add document button
please guide me towards both the initializations
class DocumentForm extends StatefulWidget {
bool update;
final String userName;
//final String createdBY;
DocumentForm(this.userName, this.update);
@override
State createState() {
return _DocumentFormState(this.userName, this.update);
}
}
// AddAppointmentState<AddDocument> createState() => _AddDocumentState();
class _DocumentFormState extends State<DocumentForm> {
final String userName;
String playerId = '';
bool update;
//final String createdBY;
_DocumentFormState(this.userName, this.update);
late final String date1;
late String datainput;
final List<String> items1 = ["Open", "Closed", "Cancel", "Submitted"];
String? selectedItem;
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
TextEditingController docIdController = TextEditingController();
TextEditingController docTitleController = TextEditingController();
TextEditingController tokenNoController = TextEditingController();
TextEditingController addressController = TextEditingController();
TextEditingController cityController = TextEditingController();
TextEditingController docStatusController = TextEditingController();
TextEditingController docTypeController = TextEditingController();
TextEditingController partyNameController = TextEditingController();
TextEditingController durationController = TextEditingController();
TextEditingController pinCodeController = TextEditingController();
TextEditingController rentDescController = TextEditingController();
TextEditingController startDateController = TextEditingController();
TextEditingController endDateController = TextEditingController();
late TextEditingController docstatusController = TextEditingController();
late String docType = docTypeController.text;
late final String createdBY;
final List<String> items = [
"Residential",
"Commercial",
];
String? selectedValue;
late Future<Document>? futureDocuments;
@override
void initState() {
this.update == true
? futureDocuments = DocumentController.fetchDocumentsByID(this.dId)
: futureDocuments = null;
// TODO: implement initState
super.initState();
// initPlatformState();
// initPlatformStateApt();
init();
}
@override
void dispose() {
docStatusController.dispose();
docTypeController.dispose();
super.dispose();
}
Future init() async {
// initPlatformState();
}
@override
Future<Document>? _futureDocument;
body: SafeArea(
child: SingleChildScrollView(
child: Container(
// height: MediaQuery.of(context).size.height,
//width: width * 1,
//height: MediaQuery.of(context).size.height,
alignment: Alignment.center,
padding: const EdgeInsets.all(25),
child: (_futureDocument == null)
? buildColumn(update)
: buildFutureBuilder(),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10),
topRight: Radius.circular(10))),
),
),
),
Form buildColumn(bool update) {
return Form(
key: formKey,
child: FutureBuilder<Document>(
future: futureDocuments,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasData) {
createdBY = snapshot.data!.createdBy;
this.dId = snapshot.data!.docId;
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(
height: 5,
),
// SizedBox(
// height: MediaQuery.of(context).size.height * 0.06,
// width: MediaQuery.of(context).size.width * 8,
// child:
Align(
alignment: Alignment.topLeft,
child: SizedBox(
width: MediaQuery.of(context).size.width * 0.95,
height: MediaQuery.of(context).size.height * 0.06,
// height: MediaQuery.of(context).size.height * 0.5,
child: TextFormField(
// minLines: 1,
// maxLines: 5,
// textCapitalization: TextCapitalization.words,
// //autovalidateMode: AutovalidateMode.onUserInteraction,
inputFormatters: [
// LengthLimitingTextInputFormatter(100),
FilteringTextInputFormatter.allow(
RegExp("[ ',-/ a-z A-Z á-ú Á-Ú 0-9]")),
],
controller: this.update == true
? docTitleController = TextEditingController(
text: '${snapshot.data!.docTitle}')
: docTitleController,
style: TextStyle(fontSize: 12),
// keyboardType: TextInputType.multiline,
decoration: const InputDecoration(
errorStyle: const TextStyle(fontSize: 0.05),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(30),
)),
hintStyle: TextStyle(fontSize: 12),
labelStyle: TextStyle(
fontSize: 12,
),
labelText: 'Document Title',
hintText: 'Document title required'),
// validator: ,
validator: MultiValidator(
[RequiredValidator(errorText: 'Required*')]),
),
),
),
SizedBox(
height: 20,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Align(
alignment: Alignment.topLeft,
child: SizedBox(
height: MediaQuery.of(context).size.height * 0.06,
width: MediaQuery.of(context).size.width * 0.4,
child: TextFormField(
style: TextStyle(
fontSize: 12,
),
// minLines: 1,
// maxLines: 2,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
LengthLimitingTextInputFormatter(14)
],
// //autovalidateMode: AutovalidateMode.onUserInteraction,
controller: this.update == true
? tokenNoController = TextEditingController(
text: '${snapshot.data!.tokenNo}')
: tokenNoController,
keyboardType: TextInputType.number,
decoration: const InputDecoration(
errorStyle: const TextStyle(fontSize: 0.05),
counterText: "",
border: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(30)),
),
focusColor: Color.fromARGB(255, 3, 87,
156), //Color.fromARGB(255, 253, 153, 33),
hintStyle: TextStyle(fontSize: 12),
labelStyle: TextStyle(
fontSize: 12,
),
labelText: 'Token No',
hintText: 'Token no required'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter token No';
} else if (value.length < 14) {
return 'Please enter 14 digits number';
}
return null;
},
),
),
),
SizedBox(
width: MediaQuery.of(context).size.width * 0.01,
),
Align(
alignment: Alignment.topLeft,
child: SizedBox(
height: MediaQuery.of(context).size.height * 0.06,
width: MediaQuery.of(context).size.width * 0.4,
child: TextFormField(
style: TextStyle(fontSize: 12),
// minLines: 1,
// maxLines: 2,
//autovalidateMode: AutovalidateMode.onUserInteraction,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
LengthLimitingTextInputFormatter(2)
],
controller: this.update == true
? durationController = TextEditingController(
text: '${snapshot.data!.duration}')
: durationController,
keyboardType: TextInputType.number,
decoration: const InputDecoration(
errorStyle: const TextStyle(fontSize: 0.05),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(30))),
hintStyle: TextStyle(fontSize: 12),
labelStyle: TextStyle(
fontSize: 12,
),
labelText: 'Duration(M)',
hintText: 'Duration required'),
validator: MultiValidator(
[RequiredValidator(errorText: 'Required*')],
),
),
),
),
],
),
SizedBox(
height: 20,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Align(
alignment: Alignment.topLeft,
child: SizedBox(
height: MediaQuery.of(context).size.height * 0.06,
width: MediaQuery.of(context).size.width * 0.4,
child: TextFormField(
style: TextStyle(fontSize: 12),
// //autovalidateMode: AutovalidateMode.onUserInteraction,
//FilteringTextInputFormatter.allow(RegExp("[- 0-9]")),
inputFormatters: [
FilteringTextInputFormatter.allow(
RegExp("[- 0-9]")),
LengthLimitingTextInputFormatter(10)
],
controller: this.update == true
? startDateController = TextEditingController(
text: '${snapshot.data!.startDate}')
: startDateController,
keyboardType: TextInputType.datetime,
decoration: const InputDecoration(
errorStyle: const TextStyle(fontSize: 0.05),
prefixIcon: Icon(Icons.calendar_month),
border: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(30))),
hintStyle: TextStyle(fontSize: 12),
labelStyle: TextStyle(
fontSize: 12,
),
labelText: 'Start Date',
hintText: 'yyyy-MM-dd',
),
onTap: () async {
DateTime? pickedDate = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(
1991), //DateTime.now() - not to allow to choose before today.
lastDate: DateTime(2101),
// onConfirm:widget.onChanged,
).then((pickedDate) {
if (pickedDate != null) {
// print(
// pickedDate); //pickedDate output format => 2021-03-10 00:00:00.000
String formattedDate =
DateFormat('yyyy-MM-dd')
.format(pickedDate);
print(formattedDate);
setState(() {
startDateController.text = formattedDate;
//set output date to TextField value.
});
print(startDateController.text);
} else {
print("Date is not selected");
}
});
final int dur =
int.parse(durationController.text);
var stDate =
DateTime.parse(startDateController.text);
var jiffy = Jiffy(stDate).add(
months: dur,
days: -1,
// days: 1095,
);
DateTime d = jiffy.dateTime;
String s = jiffy.format('yyyy-MM-dd');
setState(() {
endDateController.text = s.toString();
});
},
validator: MultiValidator(
[RequiredValidator(errorText: 'Required*')]),
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Container(
height: 30,
width: 150,
child: ElevatedButton(
onPressed: () {
// ******Add new document **********///////
formKey.currentState?.validate();
final isValidForm =
formKey.currentState!.validate();
if (isValidForm && (update == false)) {
final String docTitle =
docTitleController.text;
final int tokenNo =
int.parse(tokenNoController.text)
.toInt();
//final String tokenNo = tokenNoController.text;
final String partyName =
partyNameController.text;
// addStatus(selectedItem!);
final String docType =
selectedValue.toString();
final String docStatus =
selectedItem.toString();
final String address =
addressController.text;
final String city = cityController.text;
final String rentDesc =
rentDescController.text;
final String pinCode =
pinCodeController.text;
final String duration =
durationController.text;
final String startDate =
startDateController.text;
final String endDate =
endDateController.text;
final String createdBy = this.userName;
print('Username :${createdBy}');
final String updatedBy = '';
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) =>
DocumentPage(
this.userName,
)));
setState(() {
_futureDocument = createDocument(
// docId,
docTitle,
tokenNo,
partyName,
docType,
address,
city,
pinCode,
duration,
rentDesc,
docStatus,
startDate,
endDate,
createdBy,
updatedBy,
// createdAt,
);
});
// }
//}
}
///*****************/
//****Edit document ******/
else if (isValidForm && update == true) {
final int docid = snapshot.data!.docId;
final String docTitle =
docTitleController.text;
final int tokenNo =
int.parse(tokenNoController.text)
.toInt();
final String partyName =
partyNameController.text;
final String docType =
docTypeController.text;
final String city = cityController.text;
final String address =
addressController.text;
final String pinCode =
pinCodeController.text;
final String duration =
durationController.text;
final String rentDesc =
rentDescController.text;
final String docStatus =
docstatusController.text;
final String startDate =
startDateController.text;
final String endDate =
endDateController.text;
final String createdBy = this.createdBY;
final String updatedBy = this.userName;
print(
'the user name from doc edit page ${this.userName}');
setState(() {
futureDocuments = updateDocument(
docid,
docTitle,
tokenNo,
partyName,
docType,
address,
city,
pinCode,
duration,
rentDesc,
docStatus,
startDate,
endDate,
createdBy,
updatedBy);
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) =>
DocumentsDetails(
docid,
this.userName,
)));
});
}
;
},
child: const Text("Save"),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(
Color.fromARGB(255, 253, 153, 33),
//Color.fromARGB(255, 253, 153, 33)
),
shape: MaterialStateProperty.all<
RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(18.0),
//side: BorderSide(color: Colors.red)
),
)))),
],
),
],
);
}
}
return Center(child: const CircularProgressIndicator());
}),
);
//])
//);
}
FutureBuilder<Document> buildFutureBuilder() {
return FutureBuilder<Document>(
future: _futureDocument,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data!.docTitle);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
return const CircularProgressIndicator();
},
);
}
2
Answers
You can remove late since it’s already nullable. You have to also update the state after assigning it to futureDocuments.
Change
late
tonullable
values using?
operator. i.eChange from
to
Now you can assign
null
todate1
anddatainput
!