如何在颤振中从子级解决父级小部件

时间:2021-01-11 16:59:41

标签: flutter-web

在我的 flutter web 项目中,我有一个对话框,用户可以在其中选择一个项目并另外在文本字段中输入文本。 确认该对话框后,我可以简单地使用 TextController.text 访问文本字段的值。

用户选择的项目来自筹码列表。

在对话框中我设置了这个列表:

OrganizationList(
  queryUser: this.widget.queryUser,
  style: "chip",
),

这是我的 OrganizationList 类:

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:myappname/models/user.dart';
import 'package:myappname/services/database.dart';
import 'package:responsive_builder/responsive_builder.dart';

import 'organization_list_mobile.dart';
import 'organization_list_tablet.dart';

class OrganizationList extends StatelessWidget {
  final String style;
  final QueryDocumentSnapshot affiliate;
  final User queryUser;
  OrganizationList({
    this.style,
    this.affiliate,
    this.queryUser,
  });

  Stream<QuerySnapshot> _organizationsStream;

  @override
  Widget build(BuildContext context) {
    if (this.queryUser == null) {
      // all organizations
      print("all organizations");
      _organizationsStream =
          DatabaseService().organizationsCollection.snapshots();
    } else {
      // user's organizations
      print("user's organizations");
      _organizationsStream =
          DatabaseService(uid: this.queryUser.uid).getUserOrganizations();
    }
    return StreamBuilder(
        stream: _organizationsStream,
        builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
          if (snapshot.hasError) {
            return Text("Error: ${snapshot.error}");
          }
          switch (snapshot.connectionState) {
            case ConnectionState.waiting:
              return Center(child: CircularProgressIndicator());
            default:
              List<QueryDocumentSnapshot> snapshotOrganizations =
                  snapshot.data.docs;
              return ScreenTypeLayout(
                mobile: OrientationLayoutBuilder(
                  landscape: (context) => OrganizationListMobile(
                    organizations: snapshotOrganizations,
                    listTileStyle: this.style,
                    affiliate: this.affiliate,
                  ),
                  portrait: (context) => OrganizationListMobile(
                    organizations: snapshotOrganizations,
                    listTileStyle: this.style,
                    affiliate: this.affiliate,
                  ),
                ),
                tablet: OrientationLayoutBuilder(
                  portrait: (context) => OrganizationListTabletPortrait(),
                  landscape: (context) => OrganizationListMobile(),
                ),
              );
          }
        });
  }
}

目前我正在开发移动视图,所以这里是类 OrganizationListMobile:

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:myappname/services/database.dart';
import 'package:myappname/widgets/organization_popup_menu_button/organization_popup_menu_button.dart';

class OrganizationListMobile extends StatefulWidget {
  final List<QueryDocumentSnapshot> organizations;
  final String listTileStyle;
  final QueryDocumentSnapshot affiliate;
  const OrganizationListMobile({
    Key key,
    this.organizations,
    this.listTileStyle,
    this.affiliate,
  });

  @override
  _OrganizationListMobileState createState() => _OrganizationListMobileState();
}

class _OrganizationListMobileState extends State<OrganizationListMobile> {
  final organizationIds = [];

  @override
  void initState() {
    this.widget.organizations.forEach((element) {
      organizationIds.add(element.id);
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 200,
      child: ListView(
        shrinkWrap: true,
        children: widget.organizations
            .map((organization) => CustomListTile(
                  userId: this.widget.affiliate != null
                      ? this.widget.affiliate.id
                      : null,
                  organization: organization,
                  style: this.widget.listTileStyle,
                  organizationIds: this.organizationIds,
                ))
            .toList(),
      ),
    );
  }
}

class CustomListTile extends StatefulWidget {
  final userId;
  final organization;
  final style;
  final organizationIds;

  const CustomListTile(
      {Key key,
      this.userId,
      this.organization,
      this.style,
      this.organizationIds})
      : super(key: key);
  @override
  _CustomListTileState createState() => _CustomListTileState();
}

class _CustomListTileState extends State<CustomListTile> {
  bool isLoading;
  bool isSelected;
  bool isActivated;
  List selectedOrganizationIds;

  void onCheckboxChanged(BuildContext context, bool value) {
    value
        ? DatabaseService(uid: this.widget.userId)
            .setUserOrganization(context, this.widget.organization.documentID)
        : DatabaseService(uid: this.widget.userId).removeUserOrganization(
            context, this.widget.organization.documentID);
    setState(() {
      isSelected = value;
    });
  }

  void onChipChanged(BuildContext context, bool value) {
    setState(() {
      isSelected = value;
      print("onChipSelected" + value.toString());
    });
  }

  @override
  void initState() {
    switch (this.widget.style) {
      case "checkbox":
        isLoading = true;
        isSelected = false;
        _handleSelectionState(this.widget.organization.id, this.widget.userId);
        break;
      case "chip":
        isSelected = false;
        break;
    }
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    print(this.widget.organizationIds);
    switch (this.widget.style) {
      case "checkbox":
        return CheckboxListTile(
          title: Text((this.widget.organization.data()['name'] != null)
              ? this.widget.organization.data()['name']
              : ""),
          value: isSelected,
          onChanged: (!isLoading)
              ? (bool value) {
                  onCheckboxChanged(context, value);
                }
              : null,
        );
        break;
      case "popup":
        return ListTile(
          title: Text((this.widget.organization.data()['name'] != null)
              ? this.widget.organization.data()['name']
              : ""),
          trailing: OrganizationPopupMenuButton(
            organization: this.widget.organization,
          ),
        );
        break;
      default:
        /*return RadioListTile(
            title: Text((this.widget.organization.data()['name'] != null)
                ? this.widget.organization.data()['name']
                : ""),
            value: this.widget.organization.id,
            groupValue: this.widget.organizationIds,
            /*onChanged: (val) => setState(() => selectedRadioItem = val),
        );*/
            onChanged: (val) => print("selected ${val}"));
*/
        return ChoiceChip(
          label: Text((this.widget.organization.data()['name'] != null)
              ? this.widget.organization.data()['name']
              : ""),
          avatar: isSelected ? Icon(Icons.check) : null,
          selected: isSelected,
          onSelected: (bool value) {
            onChipChanged(context, value);
          },
        );

        break;
    }
  }

  _handleSelectionState(organizationId, userId) async {
    await DatabaseService(uid: userId)
        .checkAffiliatedOrganization(organizationId)
        .then((result) => setState(() {
              isSelected = result;
              isLoading = false;
            }));
  }
}

在提交对话时了解所选组织的最佳方式是什么?有没有办法简单地将值传回给父母?

也许整个设计可能会导致错误的方向。对此有何建议? 一般来说,我担心我在所有这些类之间传递了太多参数。也许有一个完全不同的解决方案我还没有使用过?

如果你们中的一位专业人士可以看看这个,我将不胜感激。

干杯!

0 个答案:

没有答案