Ошибка при использовании виджета автозаполнения (показывает, что контроллер ошибок удален)Android

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Ошибка при использовании виджета автозаполнения (показывает, что контроллер ошибок удален)

Сообщение Anonymous »

когда я использую виджет автозаполнения во флаттере, чтобы взять имя из списка и заполнить его вручную. Теперь я хочу присвоить значение его контроллеру и закрыть экран. Все в порядке, но если открыть снова, появится ошибка, контроллер будет удален

Код: Выделить всё

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 createState() => _OfficeAndEpcExpenseScreenState();
}

class _OfficeAndEpcExpenseScreenState extends State {

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(
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(
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(
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 onSelected,
Iterable 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(
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 _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 filePath = Rx(null);  // This will hold both image or PDF file
RxString fileName = ''.obs;
RxString fileBase64 = ''.obs;
RxString fileExt = ''.obs;
RxBool fileMaxSize = false.obs;

RxList  billerNameData = RxList();
RxnString selectedBillerId = RxnString();
TextEditingController billerNameController = TextEditingController();
FocusNode billerNameControllerFocusNode = FocusNode();
GlobalKey formKey = GlobalKey();

onAssignBillerList(List? 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 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');
}
}

}
Я попробовал перезагрузить контроллер и перезапустить мобильное приложение, а также изменил логику контроллера, чтобы он не удалялся, но он все равно удаляется

Подробнее здесь: https://stackoverflow.com/questions/790 ... is-dispose
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»