首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >管理状态的好方法在对话框中有一个窗体,在页面上显示它自己的阵营?

管理状态的好方法在对话框中有一个窗体,在页面上显示它自己的阵营?
EN

Stack Overflow用户
提问于 2022-10-30 00:39:04
回答 2查看 45关注 0票数 0

有关发票页面,我已经将BlocBuilder包装在一个状态页面的脚手架中,在这个主体中,在几个小部件下面是一个调用,用于在单独的文件调用中调用将来的空来创建一个对话框小部件。在对话框方法中,调用创建发票表单,该表单位于一个seprate文件中,并显示在对话框屏幕上的有状态类。在这种形式下,用户将能够从列表视图中添加和删除UI元素,我需要做的是重新构建小部件--对话框/窗体或列表视图/以反映用户所做的更改。

代码语言:javascript
运行
复制
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对话框,经过了这个页面。

代码语言:javascript
运行
复制
showDialog(
  context: context,
  builder: (context) => BlocProvider.value(
  value: blocController,
  child: InvoiceDetailsDialog(
  screenWidth: screenWidth,
  screenHeight: screenHeight),
  ),
);

该文件是调用显示对话框的原始位置,是自定义的未来返回showDialog。结果: showDialog采用电子筛检。呈现发票表单时出现错误,以代替表单显示:

代码语言:javascript
运行
复制
No Material widget found.

编辑3:修正了以前的错误,但回到我开始的位置,仍然被成功地调用,但是ui没有改变:

代码语言:javascript
运行
复制
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之外,什么都没有改变,我现在调用它如下:

代码语言:javascript
运行
复制
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事件吗?而不改变状态。目前为止我已经做过一次了。这种做法不好吗?

EN

Stack Overflow用户

发布于 2022-10-30 02:19:24

您可以在有状态构建器中包装您的对话框,然后得到设置对话框状态的方法。

票数 0
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74249808

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档