TextFormField с шаблоном блока Subbmiting null

При использовании TextFormField я не могу добавлять или обновлять данные, данные, отправленные в базу данных, всегда имеют значение null или я получаю ошибку NoSuchMethodErrorerror

I/flutter ( 6511): Another exception was thrown: NoSuchMethodError: The getter 'value' was called on null

Я построил Блок так:

class ProductsBloc {

  String id;
//  Product _product;


  // ignore: close_sinks
//  static final _productController = BehaviorSubject<Product>();
//  Stream<Product> get productOut => _productController.stream;

  // ignore: close_sinks
  final _id = BehaviorSubject<int>();
  // ignore: close_sinks
  final _title = BehaviorSubject<String>();
  // ignore: close_sinks
  final _message = BehaviorSubject<String>();
  // ignore: close_sinks
  final _price = BehaviorSubject<String>();

  Observable<int> get idOut => _id.stream;
  Observable<String> get titleOut => _title.stream.transform(_validateTitle);
  Observable<String> get message => _message.stream;
  Observable<String> get price => _price.stream;

  Function(int) get changeId => _id.sink.add;
  Function(String) get changeTitle => _title.sink.add;
  Function(String) get changeMessage => _message.sink.add;
  Function(String) get changePrice => _price.sink.add;

  final _validateTitle = StreamTransformer<String, String>.fromHandlers(handleData: (title, sink){
    if(title.isNotEmpty){
      sink.add(title);
    } else {
      sink.addError('Add some text');
    }
  });

  Future<void> createProduct({title}) {
    return db.createProduct(DateTime.now().millisecondsSinceEpoch.toString(), title.value, _message.value, _price.value);
  }

пользовательский интерфейс так:

class _ProductEditPageState extends State<ProductEditPage> {

  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  final _titleFocusNode = FocusNode();
  final _descriptionFocusNode = FocusNode();
  final _priceFocusNode = FocusNode();

  final id;
  final title;
  final message;
  final price;

  _ProductEditPageState(this.id, this.title, this.message, this.price);

  final Map<String, dynamic> _formData = {
    'title': null,
    'message': null,
    'price': null,
    'image': 'assets/food.jpg'
  };

  Widget _buildTitleTextField(ProductsBloc productBloc) {
    return StreamBuilder(
      stream: productBloc.titleOut,
      builder: (context, snapshot) {
        return TextFormField(
          focusNode: _titleFocusNode,
          onSaved: (String value){ _formData['title'] = value;},
          initialValue: title,
          decoration: InputDecoration(labelText: 'Title', errorText: snapshot.error),
        );
      },
    );
  }

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

child: Form(
            key: _formKey,
            child: ListView(
              padding: EdgeInsets.symmetric(horizontal: targetPadding / 2),
              children: <Widget>[
                _buildTitleTextField(productBloc, ),
                _buildDescriptionTextField(productBloc),
                _buildPriceTextField(productBloc),
                SizedBox(
                  height: 10.0,
                ),
                RaisedButton(
                  child: Text('Save'),
                  textColor: Colors.white,
                  onPressed: () {
                    if(id != null) {
                      productBloc.updateData(id);
                    }
                    else{
                      productBloc.createProduct(
                        title: _formData['title'],
                      );
                    }
                    Navigator.of(context).pop();
                  },

вот и моя модель

class Product {

  final db = Firestore.instance.collection('products');

  Future<void> createProduct(String docId, String title, String message, String price) async {
    await db.document(docId).setData({'id': docId, 'title': title, 'message': message, 'price': price});
  }

  void readData(String docId){
    db.document(docId).get();
  }

  Future<void> deleteData(String docId) async {
    await db.document(docId).delete();
  }

  Future<void> updateData(String docId, String title, String message, String price) async {
    await db.document(docId).updateData({'title': title, 'message': message, 'price': price});
  }

}

Product db = Product();

Я также использую пакет провайдера от flutter, поэтому считаю, что провайдер прав:

   return MultiProvider(
      providers: [
        Provider<ThemeBloc>(
          value: ThemeBloc(),
        ),
        Provider<UserBloc>(
          value: UserBloc(),
        ),
        Provider<ProductsBloc>(
          value: ProductsBloc(),
        ),
      ],
      child: StreamBuilder<ThemeData>(

использование textFields работает нормально, но мне нужно увидеть форму, заполненную некоторыми начальными данными перед редактированием, поэтому, очевидно, мне нужно иметь TextFormFields.


person key    schedule 02.04.2019    source источник


Ответы (1)


Ваш код довольно запутанный, но, насколько я вижу, вы пишете _formData['title'] в onSaved, но никогда не вызываете FormState.save().

Вы пробовали вызывать _formKey.currentState.save() в onPressed кнопки сохранения?

person Herbert Poul    schedule 02.04.2019