Как передать значение TextEditingController со страницы в действие во Flutter, используя пакет asyn c -redux? - PullRequest
0 голосов
/ 30 января 2020

Я учусь использовать пакет async-redux во Флаттере.

https://pub.dev/packages/async_redux

Образцы хороши по большей части, но довольно просты c. В частности, они показывают, как вызвать действие со страницы (т. Е. Как подключить кнопку к действию через событие onPressed). Это прекрасно работает. Однако они не показывают, как передать значение со страницы в действие. Поэтому я могу запустить событие save, но не могу отправить ему обновленные значения со страницы. Я свел свой код к следующему коду.

Кто-нибудь знает, как читать значения из textControllers и передавать их в действие? Я новичок во Flutter и пакете async-redux, и мне трудно разобраться, как он работает.

Для справки приведенный мною код должен считывать имена и фамилии из формы и отправлять их по адресу Firebase для хранилища (очевидно, что реальное приложение будет более задействованным, чем это).

Кроме того, я подтвердил, что действие достигается, потому что выполняется оператор debugPrint() в SaveSettingsAction.

import 'package:async_redux/async_redux.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/gestures.dart' show DragStartBehavior;
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

////////////////////////////////////////////////////////////////////////////////
// Main method and app.
////////////////////////////////////////////////////////////////////////////////
Store<AppState> store;

void main() {
  var state = AppState.initialState();
  store = Store<AppState>(initialState: state);
  runApp(MyApp());
}

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return StoreProvider<AppState>(
      store: store,
      child: MaterialApp(
        home: SettingsPage(),
        title: 'Sample App',
      )
    );
  }
}

////////////////////////////////////////////////////////////////////////////////
// App state.
////////////////////////////////////////////////////////////////////////////////
class AppState {

  final String firstName;
  final String lastName;

  AppState({
    this.firstName,
    this.lastName,
  });

  AppState copy({String firstName, String lastName}) {
    return new AppState(
      firstName: firstName ?? this.firstName,
      lastName: lastName ?? this.lastName,
    );
  }

  static AppState initialState() => AppState(
    firstName: "",
    lastName: "",
  );

  @override
  int get hashCode =>
    firstName.hashCode ^
    lastName.hashCode;

  bool operator ==(Object other) =>
      identical(this, other) ||
          other is AppState &&
              runtimeType == other.runtimeType &&
              firstName == other.firstName &&
              lastName == other.lastName;

  @override
  String toString() {
    return 'AppState{'
        'firstName: $firstName,'
        'lastName: $lastName}';
  }
}

////////////////////////////////////////////////////////////////////////////////
// Save settings action (ignore the persistence logic here - this is just a
// placeholder until we can read from the page properly).
////////////////////////////////////////////////////////////////////////////////
class SaveSettingsAction extends ReduxAction<AppState> {
  final String firstName;
  final String lastName;

  SaveSettingsAction({this.firstName, this.lastName});

  @override
  Future<AppState> reduce() async {

    // Log that this action has been reached.
    debugPrint("Start of reduce function in SaveSettingsAction.");

    // Add values to Firebase (so we have history).
    Firestore.instance
        .collection('users')
        .add({
      "firstName": firstName,
      "lastName": lastName,
    });

    // Return state with updated values.
    return state.copy(
      firstName: this.firstName,
      lastName: this.lastName,
    );
  }
}

////////////////////////////////////////////////////////////////////////////////
// Settings connector.
////////////////////////////////////////////////////////////////////////////////
class SettingsConnector extends StatelessWidget {
  SettingsConnector({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return StoreConnector<AppState, SettingsViewModel>(
      model: SettingsViewModel(),
      builder: (BuildContext context, SettingsViewModel vm) => SettingsPage(
        firstName: vm.firstName,
        lastName: vm.lastName,
        onSaveSettings: vm.onSaveSettings,
      ),
    );
  }
}

////////////////////////////////////////////////////////////////////////////////
// Settings view model.
////////////////////////////////////////////////////////////////////////////////
class SettingsViewModel extends BaseModel<AppState> {
  SettingsViewModel();

  String firstName;
  String lastName;
  VoidCallback onSaveSettings;

  SettingsViewModel.build({
    @required this.firstName,
    @required this.lastName,
    @required this.onSaveSettings,
  }) : super (equals: [firstName, lastName]);

  @override
  SettingsViewModel fromStore() => SettingsViewModel.build(
    firstName: state.firstName,
    lastName: state.lastName,
    onSaveSettings: () => dispatch(SaveSettingsAction()),
  );
}

////////////////////////////////////////////////////////////////////////////////
// Settings page.
////////////////////////////////////////////////////////////////////////////////
class SettingsPage extends StatelessWidget {
  final String firstName;
  final String lastName;
  final VoidCallback onSaveSettings;

  final TextEditingController firstNameController;
  final TextEditingController lastNameController;

  SettingsPage({
    Key key,
    this.firstName,
    this.lastName,
    this.onSaveSettings,
    this.firstNameController,
    this.lastNameController,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: <Widget>[
          Scrollbar(
            child: SingleChildScrollView(
              dragStartBehavior: DragStartBehavior.down,
              padding: const EdgeInsets.symmetric(horizontal: 4.0),
              child: Padding(
                padding: const EdgeInsets.all(16.0),
                child: Column(
                  children: <Widget>[
                    TextFormField(
                      controller: firstNameController,
                      decoration: const InputDecoration(
                        icon: Icon(Icons.person),
                        labelText: 'First Name',
                      ),
                      initialValue: firstName,
                    ),
                    TextFormField(
                      controller: lastNameController,
                      decoration: const InputDecoration(
                        icon: Icon(Icons.person),
                        labelText: 'Last Name',
                      ),
                      initialValue: lastName,
                    ),
                    Padding(
                      padding: const EdgeInsets.only(top: 16.0),
                      child: RaisedButton(
                        // How do we get the textController values to the onSaveSettings action?
                        onPressed: onSaveSettings,
                        child: const Text(
                            'Save Settings',
                            style: TextStyle(fontSize: 16)
                        ),
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...