有关发票页面,我已经将BlocBuilder包装在一个状态页面的脚手架中,在这个主体中,在几个小部件下面是一个调用,用于在单独的文件调用中调用将来的空来创建一个对话框小部件。在对话框方法中,调用创建发票表单,该表单位于一个seprate文件中,并显示在对话框屏幕上的有状态类。在这种形式下,用户将能够从列表视图中添加和删除UI元素,我需要做的是重新构建小部件--对话框/窗体或列表视图/以反映用户所做的更改。
import 'package:flutter/material.dart';
import 'dart:developer' as dev;
import 'package:track/src/features/invoices/application/bloc.dart';
import 'package:track/src/features/invoices/application/events.dart';
import 'package:track/src/features/invoices/application/pdf_invoice_api.dart';
class InvoiceForm extends StatefulWidget {
final InvoiceBlocController blocController;
const InvoiceForm(this.blocController, {Key? key}) : super(key: key);
@override
State<InvoiceForm> createState() => _InvoiceFormState();
}
class _InvoiceFormState extends State<InvoiceForm> {
final _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextFormField(
controller: TextEditingController()
..text = widget.blocController.invoice.client,
validator: (value) {
value!.isEmpty ? 'Enter a value for client' : null;
},
style: Theme.of(context).textTheme.labelMedium,
decoration: InputDecoration(
focusedBorder: const UnderlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
),
),
enabledBorder: const UnderlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
),
),
labelText: 'Client:',
labelStyle: Theme.of(context).textTheme.labelMedium),
),
TextFormField(
controller: TextEditingController()
..text =
'${widget.blocController.invoice.projectNumber}-${widget.blocController.invoice.invoiceNumber}',
validator: (value) {
value!.isEmpty ? 'Enter a valid project number' : null;
},
style: Theme.of(context).textTheme.labelMedium,
decoration: InputDecoration(
focusedBorder: const UnderlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
),
),
enabledBorder: const UnderlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
),
),
labelText: 'Client:',
labelStyle: Theme.of(context).textTheme.labelMedium),
),
ListView.builder(
shrinkWrap: true,
itemCount: widget.blocController.invoice.items.length,
itemBuilder: (context, index) {
final item = widget.blocController.invoice.items[index];
return ListTile(
contentPadding: EdgeInsets.zero,
trailing: IconButton(
onPressed: () {
widget.blocController.add(DeleteItemFromInvoice(index));
},
icon: Icon(Icons.delete)),
title: Column(
children: [
Row(
children: [
itemTextFormField(
initialValue: item.name ?? '',
labelText: 'name',
index: index),
SizedBox(width: 20),
itemTextFormField(
initialValue: item.description ?? '',
labelText: 'description',
index: index),
],
),
Row(
children: [
itemTextFormField(
initialValue: item.quantity.toString(),
labelText: 'quantity',
index: index),
SizedBox(width: 20),
itemTextFormField(
initialValue: item.costBeforeVAT.toString(),
labelText: 'Cost Before VAT',
index: index),
],
),
SizedBox(height: 30),
Divider(
thickness: 2,
color: Colors.black,
)
],
),
);
},
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
IconButton(
onPressed: () {
dev.log('button clicked to add new item');
widget.blocController.add(AddNewItemToInvoice());
},
icon: Icon(Icons.add)),
IconButton(
onPressed: () async {
_formKey.currentState!.save();
Navigator.pop(context);
await PdfInvoiceApi.generate(widget.blocController.invoice);
},
icon: Icon(Icons.send))
],
)
],
),
);
}
Expanded itemTextFormField({
required String initialValue,
required String labelText,
required int index,
}) {
return Expanded(
child: TextFormField(
controller: TextEditingController()..text = initialValue,
onSaved: (newValue) {
widget.blocController.add(UpdateInvoiceDetails(index));
},
style: Theme.of(context).textTheme.labelMedium,
decoration: InputDecoration(
focusedBorder: const UnderlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
),
),
enabledBorder: const UnderlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
),
),
labelText: labelText,
labelStyle: Theme.of(context).textTheme.labelMedium,
),
),
);
}
}InvoiceDialog源代码:https://pastebin.com/PCjmCWsk InvoiceDialog源代码:https://pastebin.com/VS5CG22D

编辑2:尽我所能对每个Mostafa组做了很多修改,在这里按下了截止日期,所以真的需要一些帮助:这些更改都是在主页面上调用Show对话框,经过了这个页面。
showDialog(
context: context,
builder: (context) => BlocProvider.value(
value: blocController,
child: InvoiceDetailsDialog(
screenWidth: screenWidth,
screenHeight: screenHeight),
),
);该文件是调用显示对话框的原始位置,是自定义的未来返回showDialog。结果: showDialog采用电子筛检。呈现发票表单时出现错误,以代替表单显示:
No Material widget found.编辑3:修正了以前的错误,但回到我开始的位置,仍然被成功地调用,但是ui没有改变:
Widget build(BuildContext context) {
final blocController = BlocProvider.of<InvoiceBlocController>(context);
return Center(
child: Material(color: Colors.red,
borderRadius: BorderRadius.circular(50),
child: SizedBox(
width: screenWidth / 2, height: screenHeight / 2,
child: Padding(padding: const EdgeInsets.all(20),
child: Column(children: [
Expanded(child: ListView(children: [
Text('Invoices',
style: Theme.of(context)
.textTheme.bodyLarge?.copyWith(color: Colors.white)),
InvoiceForm()
]))])))));
}作为表单,除了通过一个方法传递blocController之外,什么都没有改变,我现在调用它如下:
class _InvoiceFormState extends State<InvoiceForm> {
final _formKey = GlobalKey<FormState>();
late final InvoiceBlocController blocController;
@override
void initState() {
blocController = BlocProvider.of<InvoiceBlocController>(context);
super.initState();
}还是什么都没变。
编辑4: Set状态是工作的,并保留在区块代码正在执行,如果我点击,添加两个项目将被添加或删除将删除两个项目。但随着赛特国家的评论,它又回到了不重建的状态。暂时使用setstate,但没有预告。
编辑5:如果你还在被希望地关注着它,就不要这样做。我可以继续添加像: add(NewItem)、add(deleteItem)、add(GeneratePDF)这样的add事件吗?而不改变状态。目前为止我已经做过一次了。这种做法不好吗?
发布于 2022-10-30 02:19:24
您可以在有状态构建器中包装您的对话框,然后得到设置对话框状态的方法。
https://stackoverflow.com/questions/74249808
复制相似问题