Flutter - использование того же провайдера для обновления выпадающего списка и отправки данных в другой виджет - PullRequest
0 голосов
/ 06 февраля 2020

Я хочу передать выбранное значение из DropDown его родителю, а затем потомку через конструктор, после этого списка обновлений с помощью функций setState.

Итак, я хочу, чтобы выбранное значение из раскрывающегося списка было доступно в потомке Ограничений (UserOffers).

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

Сейчас я использую провайдера для обновления данных только в Dropdown, но я не знаю, как его передать.

Класс CountryProvider:

class CountryProvider with ChangeNotifier {
  List<String> _items = [
    "Argentina",
    "Brazil",
    ...
   "Spain",
    "Switzerland",
  ];

  String _selectedItem;

  List<String> get items => _items;

  String get selected => _selectedItem;

  void setSelectedItem(String s) {
    _selectedItem = s;
    notifyListeners();
  }
}

CountryDropDown класс:

class CountryDropDown extends StatefulWidget {
  @override
  _CountryDropDownState createState() => _CountryDropDownState();
}
class _CountryDropDownState extends State<CountryDropDown> {
  @override
  void initState() {
    super.initState();
  }
...
          ChangeNotifierProvider<CountryProvider>(
            create: (context) => CountryProvider(),
            child: Container(
              width: 215,
              child: Consumer<CountryProvider>(
                builder: (_, provider, __) {
                  return DropdownButton<String>(
                    hint: Text("Not selected"),
                    icon: Icon(Icons.flight),
                    value: dropdownValue,
                    onChanged: (String newValue) {
                      provider.setSelectedItem(newValue);
                      dropdownValue = provider.selected;
                      print(newValue);
                    },
                    items: provider.items
                        .map<DropdownMenuItem<String>>((String value) {
                      return DropdownMenuItem<String>(
                        value: value,
                        child: Text(value),
                      );
                    }).toList(),
                  );
...

И родитель:

Класс ограничений:

class Restrictions extends StatefulWidget {
  @override
  _RestrictionsState createState() => _RestrictionsState();
}

class _RestrictionsState extends State<Restrictions> {
  @override
  void initState() {
    super.initState();
  }
...
Column(
                  children: <Widget>[
                    Container(
                      margin: EdgeInsets.only(left: 20),
                      child: FieldDropDown(),
                    ),
                    Container(
                      padding: EdgeInsets.only(top: 10),
                      margin: EdgeInsets.only(left: 20),
                      child: CountryDropDown(),
                    ),
                  ],
                ),
                Container(
                  child: DateSelector(),
                ),
              ],
            ),
            Container(
              child: UserOffers(
                country: selectedCountry,
                field: selectedField,
              ),
...

1 Ответ

0 голосов
/ 08 февраля 2020

@ Борас! Вы проделали большую работу для меня со всеми ....

Я думаю, вам нужно поднять состояние выше вверх по дереву виджетов, чтобы UserOffers мог измениться, когда пользователь выбирает страну из выпадающего списка. menu.

Полный пример приложения ниже.

Обратите внимание, что я изменил название класса модели на SingleSelectCountry. Экземпляр этого модельного класса не является поставщиком. Экземпляр этого модельного класса - это то, что предоставляется поставщиком. Там есть важное различие.

Обратите внимание, что все виджеты расширяются StatelessWidget. Часто с поставщиком пакетов вы можете избежать использования StatefulWidget.

import 'dart:collection';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

// Model ---------------------------------------------------

class SingleSelectCountry with ChangeNotifier {
  final List<String> _items = <String>[
    "Argentina",
    "Belgium",
    "Brazil",
    "Denmark",
    "England",
    "France",
    "Finland",
    "Germany",
    "Holland",
    "Ireland",
    "Norway",
    "Poland",
    "Scotland",
    "Spain",
    "Sweden",
    "Switzerland",
    "Wales",
  ];

  String _selectedItem;

  UnmodifiableListView<String> get items {
    return UnmodifiableListView(this._items);
  }

  String get selected {
    return this._selectedItem;
  }

  set selected(final String item) {
    this._selectedItem = item;
    this.notifyListeners();
  }
}

// User Interface ------------------------------------------

void main() {
  return runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(final BuildContext context) {
    // The provider has to be in the widget tree higher than
    // both `CountryDropDown` and `UserOffers`.
    return MultiProvider(
      providers: [
        ChangeNotifierProvider<SingleSelectCountry>(
          create: (final BuildContext context) {
            return SingleSelectCountry();
          },
        ),
      ],
      child: Scaffold(
        appBar: AppBar(
          title: Text('My Home Page'),
        ),
        body: Restrictions(),
      ),
    );
  }
}

class Restrictions extends StatelessWidget {
  @override
  Widget build(final BuildContext context) {
    return Column(
      children: <Widget>[
        CountryDropDown(),
        UserOffers(),
      ],
    );
  }
}

class CountryDropDown extends StatelessWidget {
  @override
  Widget build(final BuildContext context) {
    return Consumer<SingleSelectCountry>(
      builder: (
        final BuildContext context,
        final SingleSelectCountry singleSelectCountry,
        final Widget child,
      ) {
        return DropdownButton<String>(
          hint: const Text("Not selected"),
          icon: const Icon(Icons.flight),
          value: singleSelectCountry.selected,
          onChanged: (final String newValue) {
            singleSelectCountry.selected = newValue;
          },
          items: singleSelectCountry.items.map<DropdownMenuItem<String>>(
            (final String value) {
              return DropdownMenuItem<String>(
                value: value,
                child: Text(value),
              );
            },
          ).toList(),
        );
      },
    );
  }
}

class UserOffers extends StatelessWidget {
  @override
  Widget build(final BuildContext context) {
    return Consumer<SingleSelectCountry>(
      builder: (
        final BuildContext context,
        final SingleSelectCountry singleSelectCountry,
        final Widget child,
      ) {
        return Text(singleSelectCountry.selected ?? '');
      },
    );
  }
}
...