when i am using AutoComplete widget in flutter to take name from list and fill manually also .Now i want to assign a value to its controller and close screen .its ok but if open again it show error , controller is dispose
import 'package:shunya_core/models/claims_model/claims_list_model.dart' as c;
class OfficeAndEpcExpenseScreen extends StatefulWidget {
cData.Data? data;
String userLoginId;
String expenseTypeId;
c.Data? voucherData;
OfficeAndEpcExpenseScreen({super.key, required this.data, required this.userLoginId, required this.expenseTypeId, this.voucherData});
@override
State<OfficeAndEpcExpenseScreen> createState() => _OfficeAndEpcExpenseScreenState();
}
class _OfficeAndEpcExpenseScreenState extends State<OfficeAndEpcExpenseScreen> {
late AppLocalizations appLanguage;
final OfficeAndEpcController _controller = Get.put(OfficeAndEpcController());
@override
void initState() {
// TODO: implement initState
super.initState();
onInIt();
}
onInIt(){
_controller.fileMaxSize.value = false;
_controller.onAssignBillerList(widget.data!.vendors);
if(widget.voucherData != null){
log('Moit tnilllsdf');
_controller.onAutoFillVoucherData(voucherData: widget.voucherData);
}
}
@override
void dispose() {
// TODO: implement dispose
_controller.selectedEntityId.value = null;
_controller.selectedGlcId.value = null;
_controller.selectedPaymentModeId.value = null;
_controller.selectedBillerId.value = null;
_controller.billAmount.clear();
_controller.billNumber.clear();
_controller.billDate.clear();
_controller.purposeOfExpenseController.clear();
// _controller.billerNameData.clear();
// // _controller.billerNameList!.clear();
_controller.filePath.value = null;
_controller.fileName.value="";
_controller.fileExt.value="";
// _controller.billerNameController.text="";
super.dispose();
}
@override
Widget build(BuildContext context) {
final mq = MediaQuery.of(context).size;
appLanguage = AppLocalizations.of(context)!;
return Expanded(
child: Form(
key: _controller.formKey,
child: SingleChildScrollView(
child: Column(
children: [
const SizedBox(height: 10),
_buildEntityTypeAndGlcField(),
const SizedBox(height: 10),
_buildBillNumberField(),
const SizedBox(height: 10),
_buildBillDateAndBilAmountField(),
const SizedBox(height: 10),
_buildBillerNameAndPaymentMode(),
const SizedBox(height: 10),
_buildPurposeOfExpense(),
const SizedBox(height: 40),
_buildFilePickerSection(),
const SizedBox(height: 100,),
_buildSaveButton(appLanguage: appLanguage, mq: mq),
const SizedBox(height: 15),
],
),),),);
}
Widget _buildEntityTypeAndGlcField(){
return Row(
crossAxisAlignment: CrossAxisAlignment.start,mainAxisAlignment: MainAxisAlignment.start,
children: [
// Expanded(
// child: CommonWidgets.buildDropdownField(label: appLanguage.entity_type, items: widget.data!.entityTypes!.map((v)=>v.entityType).toList(),
// onChanged: (val){
// _controller.onEntityTypeOnChanged(val: val!, data: widget.data);
// }, hint: appLanguage.please_select, fontSize: mq.height * 0.016, value: null,validator: (val){
// if(val != null && !val.isBlank!){
// return null;
// }else{
// return appLanguage.required;
// }
// }),),
Expanded(child: CommonWidgets.buildDropdownField<String>(
label: appLanguage.entity_type,
items: widget.data!.entityTypes!.map((expenseType) {
return expenseType.entityTypeId.toString(); // Use ID as item
}).toList(),
onChanged: (selectedId) {
if (selectedId != null) {
_controller.onEntityTypeOnChanged(selectedId: selectedId, data: widget.data, voucherData: null);
}
},
hint: appLanguage.please_select,
fontSize: mq.height * 0.016, // Adjust font size as needed
value: _controller.selectedEntityId.value, // The currently selected expenseTypeId
displayItem: (id) {
final entityType = widget.data!.entityTypes!.firstWhere(
(type) => type.entityTypeId.toString() == id,
orElse: () => cData.EntityTypes(entityTypeId: int.parse(id), entityType: ''),
);
return entityType.entityType ?? ''; // Display the expense name
},
)),
const SizedBox(width: 10,),
// Expanded(
// child: CommonWidgets.buildDropdownField(label: appLanguage.glc, items: widget.data!.glcs!.map((v)=>v.glcName).toList(),
// onChanged: (val){
// _controller.onGlcListOnChanged(val: val!, data: widget.data);
// }, hint: appLanguage.please_select, fontSize: mq.height * 0.016, value: null,validator: (val){
// if(val != null && !val.isBlank!){
// return null;
// }else{
// return appLanguage.required;
// }
// }),)
Expanded(child: CommonWidgets.buildDropdownField<String>(
label: appLanguage.glc,
items: widget.data!.glcs!.map((glcs) {
return glcs.glcId.toString(); // Use ID as item
}).toList(),
onChanged: (selectedId) {
if (selectedId != null) {
_controller.onGlcListOnChanged(selectedId: selectedId,data: widget.data, voucherData: null);
}
},
hint: appLanguage.please_select,
fontSize: mq.height * 0.016, // Adjust font size as needed
value: _controller.selectedGlcId.value, // The currently selected expenseTypeId
displayItem: (id) {
final glcType = widget.data!.glcs!.firstWhere(
(type) => type.glcId.toString() == id,
orElse: () => cData.Glcs(glcId: id, glcName: ''),
);
return glcType.glcName ?? ''; // Display the expense name
},
)),
],
);
}
Widget _buildBillNumberField(){
return CommonWidgets.buildTextField(appLanguage: appLanguage, label: appLanguage.bill_number.replaceAll('*', ''),
controller: _controller.billNumber, hint: appLanguage.enter_number, maxLines: 1,
onChanged: (val){ },
onTap: () async{ },validator: (val){
if(val != null && !val.isBlank!){
return null;
}else{
return appLanguage.required;
}
}
);
}
Widget _buildBillDateAndBilAmountField(){
return Row(
crossAxisAlignment: CrossAxisAlignment.start,mainAxisAlignment: MainAxisAlignment.start,
children: [
Expanded(child: CommonWidgets.buildTextField(appLanguage: appLanguage, label: appLanguage.bill_date,
controller: _controller.billDate, hint: 'dd/mm/yyyy', maxLines: 1,
onChanged: (val){ },
onTap: () async{
DateTime firstD = DateTime.now().subtract(const Duration(days: 365));
final date = await CommonMethods.onDatePicker(context: context, initialDate: DateTime.now(), firstDate: firstD, lastDate: DateTime.now(),);
if (date != null) {
String? d = CommonMethods.showFormattedDate(date, formatFor: 1);
_controller.billDate.text = d ?? '';
}
},
inputFormatters: [LengthLimitingTextInputFormatter(10)],
validator: (val){
if(val != null && !val.isBlank!){
return null;
}else{
return appLanguage.required;
}
})),
const SizedBox(width: 10,),
Expanded(child: CommonWidgets.buildTextField(appLanguage: appLanguage, label: appLanguage.bill_amount,
controller: _controller.billAmount, hint: appLanguage.enter_amount, maxLines: 1,
onChanged: (val){ },
onTap: () async{ },
validator: (val){
if(val != null && !val.isBlank!){
return null;
}else{
return appLanguage.required;
}
})),
],
);
}
Widget _buildBillerNameAndPaymentMode(){
return Row(
crossAxisAlignment: CrossAxisAlignment.start,mainAxisAlignment: MainAxisAlignment.start,
children: [
Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start,
children: [
CommonMethods.onAutoSizeText(appLanguage.biller_name),
const SizedBox(height: 7),
Autocomplete<cData.Vendors>(
optionsBuilder: (TextEditingValue textEditingValue) {
return _filterBillerNameList(textEditingValue.text);
},
onSelected: (cData.Vendors selectedVendor) {
_controller.onBillerSelected(selectedVendor);
_controller.billerNameControllerFocusNode.unfocus();
},
fieldViewBuilder: (BuildContext context,
TextEditingController textEditingController,
FocusNode focusNode,
VoidCallback onFieldSubmitted) {
_controller.billerNameController = textEditingController;
_controller.billerNameControllerFocusNode = focusNode;
return TextFormField(
controller: textEditingController,
focusNode: focusNode,
decoration: CommonMethods.onTextFieldDecoration(hintText: appLanguage.enter_name),
onChanged: (text) {
// Check if the entered text matches any vendor
var matchingVendors = _controller.billerNameData.where((vendor) {
return vendor.vendorName?.toLowerCase() == text.toLowerCase();
}).toList();
if (matchingVendors.isEmpty) {
// If no vendor matches, set selectedBillerId.value to "0"
_controller.selectedBillerId.value = "0";
}
},onTap: () {
// Refocus and show filtered list when user taps on the text field again
if (!_controller.billerNameControllerFocusNode.hasFocus) {
_controller.billerNameControllerFocusNode.requestFocus(); // Focus on the text field
}
},
validator: (val) {
if (val != null && val.isNotEmpty) {
return null;
} else {
return appLanguage.required;
}
},
);
},
optionsViewBuilder: (BuildContext context,
AutocompleteOnSelected<cData.Vendors> onSelected,
Iterable<cData.Vendors> options) {
double maxDropdownHeight = 300.0; // Maximum height for the dropdown
double minDropdownHeight = 110.0; // Minimum height for the dropdown
double itemHeight = 48.0; // Approximate height of each item
double calculatedHeight = itemHeight * options.length; // Calculate height based on number of items
// Ensure height is at least minDropdownHeight but not more than maxDropdownHeight
double dropdownHeight = calculatedHeight.clamp(minDropdownHeight, maxDropdownHeight);
return Align(
alignment: Alignment.topLeft,
child: Material(
child: SizedBox(
width: MediaQuery.of(context).size.width - 80,
height: dropdownHeight,
child: ListView.builder(
itemCount: options.length,
itemBuilder: (BuildContext context, int index) {
final cData.Vendors vendor = options.elementAt(index);
return GestureDetector(
onTap: () {
onSelected(vendor);
},
child: Container(
margin: const EdgeInsets.all(5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(vendor.vendorName ?? '', style: const TextStyle(fontSize: 16)),
Divider(thickness: 1, color: AppColors.grey),
],),
),);},
),),),
);},)
],),),
const SizedBox(width: 10),
Expanded(child: CommonWidgets.buildDropdownField<String>(
label: appLanguage.payment_mode,
items: widget.data!.paymentModes!.map((paymentMode) {
return paymentMode.paymentModeId.toString(); // Use ID as item
}).toList(),
onChanged: (selectedId) {
if (selectedId != null) {
_controller.onPaymentModeOnChanged(selectedId: selectedId,data: widget.data, voucherData: null);
}
},
hint: appLanguage.please_select,
fontSize: mq.height * 0.016, // Adjust font size as needed
value: _controller.selectedPaymentModeId.value, // The currently selected expenseTypeId
displayItem: (id) {
final pMode = widget.data!.paymentModes!.firstWhere(
(type) => type.paymentModeId.toString() == id,
orElse: () => cData.PaymentModes(paymentModeId: int.parse(id), paymentMode: ''),
);
return pMode.paymentMode ?? ''; // Display the expense name
},
)),
],
);
}
Widget _buildPurposeOfExpense(){
return CommonWidgets.buildTextField(appLanguage: appLanguage, label: appLanguage.description,
controller: _controller.purposeOfExpenseController, hint: '', maxLines: 1,
onChanged: (val){ },
onTap: () async{ },
validator: (val){
if(val != null && !val.isBlank!){
return null;
}else{
return appLanguage.required;
}
}
);
}
Future<Iterable<cData.Vendors>> _filterBillerNameList(String query) async {
if (query.isEmpty && _controller.billerNameControllerFocusNode.hasFocus) {
return _controller.billerNameData;
} else {
return _controller.billerNameData
.where((vendor) => vendor.vendorName?.toLowerCase().contains(query.toLowerCase()) ?? false)
.toList();
}
}
Widget _buildFilePickerSection() {
return Obx(() {
final filePath = _controller.filePath.value;
final fileName = _controller.fileName.value;
return Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,mainAxisAlignment: MainAxisAlignment.start,
children: [
AutoSizeText('${appLanguage.photo} :',
style: CommonMethods.getTextStyleBold(
fontSize: mq.height * 0.015, fontColor: Colors.black)),
AutoSizeText('(${appLanguage.file_max_size_is_2mb})', style: TextStyle(fontSize: mq.height * 0.01, color: _controller.fileMaxSize.value ? AppColors.red : AppColors.black),)
],),
),
const Spacer(),
Expanded(
child: Column(
children: [
GestureDetector(
onTap: _controller.onFilePicker,
child: filePath != null
? _buildFileContainer(filePath, fileName)
: _buildPlaceholderContainer(),
),
],),
),],);
});
}
Widget _buildFileContainer(File file, String fileName) {
// Check if it's an image file
final isImage = fileName.toLowerCase().endsWith('.jpg') ||
fileName.toLowerCase().endsWith('.png') ||
fileName.toLowerCase().endsWith('.jpeg');
return Container(
height: 100,
width: 90,
decoration: BoxDecoration(
border: Border.all(width: 1),
borderRadius: BorderRadius.circular(12),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(12),
child: isImage
? Image.file(file, width: 90, height: 115, fit: BoxFit.fill) // Show image
: const Center(child: Icon(Icons.picture_as_pdf, size: 40)), // Show PDF icon
),
);
}
Widget _buildPlaceholderContainer() {
return Column(
children: [
Container(
height: 100,
width: 90,
decoration: BoxDecoration(
border: Border.all(width: 1),
borderRadius: BorderRadius.circular(12),
),
child: const Icon(Icons.add_a_photo, size: 40),
),
],
);
}
Widget _buildSaveButton({required AppLocalizations appLanguage, required Size mq}) {
return CommonMethods.onMainAppButton(textLength: 0, maxTextLength: 0, text: appLanguage.save, height: 46, fontSize: mq.height * 0.025, clr: AppColors.lightblue,
onTap: (){
// if(_controller.filePath.value != null){
// log('file2');
// _controller.isFileSelected.value = false;
// }else{
// _controller.isFileSelected.value = true;
// }
if(_controller.filePath.value == null){
_controller.fileMaxSize.value = false;
}
if(_controller.fileMaxSize.value == false){
if(_controller.formKey.currentState!.validate()){
_controller.onSaveOfficeAndEpcExpense(context: context, appLanguage: appLanguage, userLoginId: widget.userLoginId, expenseTypeId: widget.expenseTypeId);
log('Success validate');
}else{
log('Failed validate');}
}
});
}
}
import 'package:shunya_core/models/claims_model/claim_reimbursement_data_model.dart' as cData;
import 'package:shunya_core/models/claims_model/claims_list_model.dart' as c;
class OfficeAndEpcController extends GetxController {
RxnString selectedEntityId = RxnString();
RxnString selectedGlcId = RxnString();
RxnString selectedPaymentModeId = RxnString();
TextEditingController billNumber = TextEditingController();
TextEditingController billDate = TextEditingController();
TextEditingController billAmount = TextEditingController();
TextEditingController purposeOfExpenseController = TextEditingController();
// RxBool isFileSelected = RxBool(false);
Rx<File?> filePath = Rx<File?>(null); // This will hold both image or PDF file
RxString fileName="".obs;
RxString fileBase64 = ''.obs;
RxString fileExt="".obs;
RxBool fileMaxSize = false.obs;
RxList<cData.Vendors> billerNameData = RxList<cData.Vendors>();
RxnString selectedBillerId = RxnString();
TextEditingController billerNameController = TextEditingController();
FocusNode billerNameControllerFocusNode = FocusNode();
GlobalKey<FormState> formKey = GlobalKey<FormState>();
onAssignBillerList(List<cData.Vendors>? l) {
log('OnBillerName ka listt ');
billerNameData!.value = l ?? [];
log('OnBillerName ka listt2 :: $billerNameData');
}
onBillerSelected(cData.Vendors selectedVendor) {
billerNameController.text = selectedVendor.vendorName ?? '';
// You can store the selected vendor's ID in a variable
selectedBillerId.value = selectedVendor.vendorId;
}
onEntityTypeOnChanged(
{required String selectedId, cData.Data? data, c.Data? voucherData}) {
if(voucherData == null){
if(data != null){
// Find the ExpenseTypes object that matches the selected expenseTypeId
var selectedEntityType = data!.entityTypes!
.firstWhere((expenseType) => expenseType.entityTypeId.toString() == selectedId);
// Set the selectedExpenseId and log it
selectedEntityId.value = selectedEntityType.entityTypeId.toString();
// Optionally log or update other fields if needed
log('Selected Expense Type ID1 :: $selectedEntityType');
log('Selected Expense Name1 :: ${selectedEntityType.entityTypeId}');
}
}else{
// Set the selectedExpenseId
selectedEntityId.value = selectedId;
// Optionally log or update other fields if needed
log('Selected Expense Type ID2 :: ');
log('Selected Expense Name2 :: ');
}
}
onGlcListOnChanged(
{required String selectedId, cData.Data? data, c.Data? voucherData}) {
if(voucherData == null){
if(data != null){
// Find the ExpenseTypes object that matches the selected expenseTypeId
var selectedGlc = data!.glcs!
.firstWhere((glcList) => glcList.glcId.toString() == selectedId);
selectedGlcId.value = selectedGlc!.glcId.toString();
// Optionally log or update other fields if needed
log('Selected Glcc Type ID1 :: $selectedGlc');
log('Selected Glc Name1 :: ${selectedGlc.glcId}');
}
}else{
// Set the selectedExpenseId
selectedGlcId.value = selectedId;
// Optionally log or update other fields if needed
log('Selected Expense Type ID2 :: ');
log('Selected Expense Name2 :: ');
}
}
onPaymentModeOnChanged(
{required String selectedId, cData.Data? data, c.Data? voucherData}) {
if(voucherData == null){
if(data != null){
// Find the ExpenseTypes object that matches the selected expenseTypeId
var selectedPaymentModeType = data!.paymentModes!
.firstWhere((pMode) => pMode.paymentModeId.toString() == selectedId);
// Set the selectedExpenseId and log it
selectedPaymentModeId.value = selectedPaymentModeType.paymentModeId.toString();
// Optionally log or update other fields if needed
log('Selected Payment Type ID1 :: $selectedPaymentModeType');
log('Selected Payment Mode Name1 :: ${selectedPaymentModeType.paymentModeId}');
}
}else{
// Set the selectedExpenseId
selectedPaymentModeId.value = selectedId;
// Optionally log or update other fields if needed
log('Selected Expense Type ID2 :: ');
log('Selected Expense Name2 :: ');
}
}
Future<void> onFilePicker() async {
// Reset file
filePath.value = null;
fileName.value="";
fileBase64.value="";
fileExt.value="";
fileMaxSize.value = false;
// Ask user for file type
final result = await FilePicker.platform.pickFiles(
allowMultiple: false,
type: FileType.custom,
allowedExtensions: ['jpg', 'png', 'jpeg', 'pdf'], // Restricting to image and PDF formats
);
if (result != null && result.files.single.path != null) {
final selectedFile = File(result.files.single.path!);
fileName.value = result.files.single.name;
// If it's an image, compress it
if (result.files.single.extension != null && ['jpg', 'png', 'jpeg'].contains(result.files.single.extension!.toLowerCase())) {
filePath.value = selectedFile;
final compressedImage = await PickFileAndCompress.onSingleImageCompressor(
imageFile: selectedFile,
atQuality: 55,
);
filePath.value = compressedImage;
fileBase64.value = await PickFileAndCompress.imageToBase64(filePath.value?.path ?? '');
} else if (result.files.single.extension != null && result.files.single.extension!.toLowerCase() == 'pdf') {
// Check PDF size
int pdfSizeInBytes = await selectedFile.length();
if (pdfSizeInBytes > 2 * 1024 * 1024) { // Check if size is greater than 2 MB
// Show a toast message
// log('Pdf size id more :: $pdfSizeInBytes');
fileMaxSize.value = true;
return; // Exit the function to prevent further processing
}else{
fileMaxSize.value = false;
// Compress the PDF
filePath.value = selectedFile;
final compressPdf = await PickFileAndCompress.compressPdf(filePath.value!);
filePath.value = compressPdf;
fileBase64.value = await PickFileAndCompress.imageToBase64(filePath.value?.path ?? '');
}
}
if (fileName.value.length >= 3) {
fileExt.value = fileName.value.substring(fileName.value.length - 3);
// log("File extension: ${fileExt.value}"); // Output: "pdf"
} else {
log("Filename is too short to determine extension.");
}
}
}
onSaveOfficeAndEpcExpense({required BuildContext context,
required AppLocalizations appLanguage, required String userLoginId, required String expenseTypeId}) async {
String? formattedDate = CommonMethods.showFormattedDate(billDate.text, formatFor: 2);
final body = {
"control": CommonMethods.getControlMap(),
"data": {
"voucher_id": "0",
"employee_id": "0",
"expense_type_id": expenseTypeId,
"expense_purpose": purposeOfExpenseController.text.toString(),
"payment_mode_id": selectedPaymentModeId.value,
"entity_id": selectedEntityId.value,
"bill_no": billNumber.text.toString(),
"bill_date": formattedDate,
"total_amount": billAmount.text.toString(),
"biller_id": selectedBillerId.value,
"biller_name": billerNameController.text.toString(),
"cgst_amount": "0",
"sgst_amount": "0",
"igst_amount": "0",
"glc_id": selectedGlcId.value,
"user_login_id": userLoginId,
"is_active": "1",
"file_ext": filePath.value != null ? fileExt.value : '',
"voucher_image" : filePath.value != null ? fileBase64.value : ''
}
};
final response = await ApiClient.fetchPostWithToast(ApiConst.claimAddOfficeExpenseApiUrl, body, true, false);
if(response != null){
var res = response['response'];
var message = response['message'];
if (res.statusCode == 200) {
// Clear list and show response dialog
CommonMethods.showResponseDialog(
context: context,
title: appLanguage.message,
msg: message,
buttonText: appLanguage.ok,
popTimes: 2,
refreshKey: 'refreshClaimList'
);
}else{
CommonMethods.showResponseDialog(
context: context,
title: appLanguage.message,
msg: message,
buttonText: appLanguage.ok,
popTimes: 1
);
}
}
}
onAutoFillVoucherData({required c.Data? voucherData}){
onEntityTypeOnChanged(selectedId: voucherData!.entityId ?? '', voucherData: voucherData);
onGlcListOnChanged(selectedId: voucherData.glcId ?? '', voucherData: voucherData);
onPaymentModeOnChanged(selectedId: voucherData.paymentModeId ?? '', voucherData: voucherData);
billNumber.text = voucherData.billNo ?? '';
String? dateFormatted = CommonMethods.showFormattedDate(voucherData.voucherDate ?? '', formatFor: 1);
billDate.text = dateFormatted ?? '';
billAmount.text = voucherData.totalAmount ?? '';
purposeOfExpenseController.text = voucherData.expensePurpose ?? '';
onBillerOnChange(voucherData.vendorName ?? '');
}
onBillerOnChange(text){
var matchingVendors = billerNameData.where((vendor) {
return vendor.vendorName?.toLowerCase() == text.toLowerCase();
}).toList();
log('BillerName1 :: $text');
if (matchingVendors.isEmpty) {
// If no vendor matches, set selectedBillerId.value to "0"
selectedBillerId.value = "0";
log('BillerName2 :: $selectedBillerId');
}else{
selectedBillerId.value = "1";
billerNameController.text = text;
log('BillerName3 :: $text');
log('BillerName4 :: $selectedBillerId');
}
}
}
I tried resetting the controller and restarting the mobile app , also changed the logic of controller to not get disposed , still its getting disposed
You need to sign in to view this answers