I got stuck with a problem in Flutter: The following assertion was thrown building TextField, it flesh me a stranger problem

12,236

Solution 1

The exception explains what happens:

TextField widgets require a Material widget ancestor.


To introduce such Material widget, you have multiple possibilities:

  • Dialog
  • Scaffold
  • Material

Example:

Material(
  child: TextField(...),
)

Solution 2

You must enclose the TextFormField in a Form widget in order to use the validate () method and in turn the save () method, to save the values of the TextFormField in String variables. Here I leave an example that appears in the documentation of Flutter => Example Forms

Share:
12,236

Related videos on Youtube

Sabatin 02
Author by

Sabatin 02

Updated on May 26, 2022

Comments

  • Sabatin 02
    Sabatin 02 almost 2 years

    I got stuck with a problem in Flutter: The following assertion was thrown building TextField, it flesh me a strange problem just for a brief moment!

    For any clarification on the code or errors, comment below and I will reply in a few minutes, because I can not wait to solve this problem and move forward without too many thoughts!!

    The error that Andoid Studio returns me is like this:

    I/flutter (26182): The following assertion was thrown building TextField(controller: I/flutter (26182): TextEditingController#e1688(TextEditingValue(text: ┤├, selection: TextSelection(baseOffset: -1, I/flutter (26182): extentOffset: -1, affinity: TextAffinity.downstream, isDirectional: false), composing: I/flutter (26182): TextRange(start: -1, end: -1))), enabled: true, decoration: InputDecoration(hintText: "Materia"), I/flutter (26182): autocorrect: true, max length enforced, onTap: null, dirty, state: _TextFieldState#73fdb): I/flutter (26182): No Material widget found. I/flutter (26182): TextField widgets require a Material widget ancestor. I/flutter (26182): In material design, most widgets are conceptually "printed" on a sheet of material. In Flutter's I/flutter (26182): material library, that material is represented by the Material widget. It is the Material widget I/flutter (26182): that renders ink splashes, for instance. Because of this, many material library widgets require that I/flutter (26182): there be a Material widget in the tree above them. I/flutter (26182): To introduce a Material widget, you can either directly include one, or use a widget that contains I/flutter (26182): Material itself, such as a Card, Dialog, Drawer, or Scaffold. I/flutter (26182): The specific widget that could not find a Material ancestor was: I/flutter (26182):
    TextField(controller: TextEditingController#e1688(TextEditingValue(text: ┤├, selection: I/flutter (26182): TextSelection(baseOffset: -1, extentOffset: -1, affinity: TextAffinity.downstream, isDirectional: I/flutter (26182):
    false), composing: TextRange(start: -1, end: -1))), enabled: true, decoration: I/flutter (26182): InputDecoration(hintText: "Materia"), autocorrect: true, max length enforced, onTap: null) I/flutter (26182): The ancestors of this widget were:

    ... and a long list of widgets

    This is my code, a very simple input form with 2 forms, "materia" and "description" and the page from where it is loaded into one TabBarView called "AssegnoPage". I use the scoped model, below you will find it. ù

    Focus on the tab of AssegnoPage: AssegnoListPage and AggiungiAssegno

    The AssegnoPage:

    import 'package:flutter/material.dart';
    
    import 'package:prova_app_book/assegno/page/aggiungi_assegno.dart'; import 'package:prova_app_book/widget/drawer.dart'; import 'assegno_list.dart'; //import '../../models/assegno.dart';
    
    class AssegnoPage extends StatelessWidget {
    
      @override   Widget build(BuildContext context) {
        return DefaultTabController(
          length: 2,
          child: Scaffold(
            drawer: Drawer(child: DrawerWidget(),),
            appBar: AppBar(
              title: Text('Gestione Assegno'),
              bottom: TabBar(
                  tabs: <Widget>[
                    Tab(
                      icon: Icon(Icons.edit),
                      text: 'Aggiungi Assegno',
                    ),
                    Tab(
                      icon: Icon(Icons.book),
                      text: 'Il tuo assegno',
                    ),
                  ],
              ),
            ),
            body: TabBarView(children: <Widget> [
              AggiungiAssegno(),
              AssegnoListPage()
            ]),
          ),
        );   } }
    

    The simply form with a submitbutton at the end:

    import 'package:flutter/material.dart';
    import 'package:scoped_model/scoped_model.dart';
    
    import '../../scoped_models/assegno.dart';
    import '../../models/assegno.dart';
    
    class AggiungiAssegno extends StatefulWidget {
      @override
      State<StatefulWidget> createState() {
        return _AggiungiAssegnoState();
      }
    }
    
    class _AggiungiAssegnoState extends State<AggiungiAssegno> {
      final Map<String, dynamic> _formData = {
        'materia': null,
        'assegno': null,
      };
      final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
    
      Widget _buildTitoloMateria(Assegno assegno) {
        return TextFormField(
          decoration: InputDecoration(hintText: 'Materia'),
          initialValue: assegno == null ? '' : assegno.materia,
          validator: (String value) {
            if (value.isEmpty) {
              return 'Il nome della materia è necessario';
            }
          },
          onSaved: (String value) {
            _formData['materia'] = value;
          },
        );
      }
    
      Widget _buildAssegno(Assegno assegno) {
        return TextFormField(
          decoration: InputDecoration(hintText: 'Assegno'),
          maxLines: 3,
          initialValue: assegno == null ? '' : assegno.assegno,
          validator: (String value) {
            if (value.isEmpty) {
              return 'L\'assegno è necessario';
            }
          },
          onSaved: (String value) {
            _formData['assegno'] = value;
          },
        );
      }
    
      void _submitForm(Function aggiungiAssegno, Function aggiornaAssegno, [int selectedAssegnoIndex]) {
        if (!_formKey.currentState.validate()) {
          return;
        }
        _formKey.currentState.save();
        if (selectedAssegnoIndex == null) {
          aggiungiAssegno(Assegno(
              materia: _formData['materia'], assegno: _formData['assegno']));
        } else {
          aggiornaAssegno(
              Assegno(
                  materia: _formData['materia'], assegno: _formData['assegno']));
        }
        Navigator.pushReplacementNamed(context, '/panoramica');
      }
    
      Widget _buildSubmitButton() {
        return ScopedModelDescendant<AssegnoModel>(
          builder: (BuildContext context, Widget child, AssegnoModel model) {
            return RaisedButton(
              child: Text('Fatto'),
              textColor: Colors.white,
              onPressed: () =>
                  _submitForm(model.aggiungiAssegno, model.aggiornaAssegno, model.selectesAssegnoIndex),
            );
          },
        );
      }
    
      Widget _buildPageContent(BuildContext context, Assegno assegno) {
        final double deviceWidth = MediaQuery.of(context).size.width;
        final double targetWidth = deviceWidth > 550.0 ? 500.0 : deviceWidth * 0.95;
        final double targetPadding = deviceWidth - targetWidth;
        return Container(
          margin: EdgeInsets.all(10.0),
          child: Form(
            key: _formKey,
            child: ListView(
              padding: EdgeInsets.symmetric(horizontal: targetPadding / 2),
              children: <Widget>[
                _buildTitoloMateria(assegno),
                SizedBox(
                  height: 20.0,
                ),
                _buildAssegno(assegno),
                SizedBox(
                  height: 20.0,
                ),
                _buildSubmitButton(),
              ],
            ),
          ),
        );
      }
    
      @override
      Widget build(BuildContext context) {
        return ScopedModelDescendant<AssegnoModel>(
          builder: (BuildContext context, Widget child, AssegnoModel model) {
            final Widget pageContent = _buildPageContent(context, model.selectedAssegno);
            return model.selectesAssegnoIndex == null
                ? pageContent
                : Scaffold(
                    appBar: AppBar(
                      title: Text('Aggiungi Assegno'),
                    ),
                    body: pageContent,
                  );
          },
        );
      }
    }
    

    The AssegnoListPage, Here, I returned the previous page, pressing the button, flutter gives me the error above!:

    import 'package:flutter/material.dart';
    import 'package:scoped_model/scoped_model.dart';
    
    //import '../../models/assegno.dart';
    import 'aggiungi_assegno.dart';
    import '../../scoped_models/assegno.dart';
    
    class AssegnoListPage extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return ScopedModelDescendant<AssegnoModel>(
          builder: (BuildContext context, Widget child, AssegnoModel model) {
            return ListView.builder(
              itemBuilder: (BuildContext context, int index) {
                return Column(
                  children: <Widget>[
                    ListTile(
                      leading: Icon(Icons.book),
                      title: Text(model.assegno[index].materia),
                      trailing: IconButton(
                          icon: Icon(Icons.edit),
                          onPressed: () {
                            model.selectAssegno(index);
                            Navigator.of(context).push(
                              MaterialPageRoute(
                                builder: (BuildContext context) {
                                  return AggiungiAssegno();
                                },
                              ),
                            );
                          }),
                    ),
                    Divider(),
                  ],
                );
              },
              itemCount: model.assegno.length,
            );
          },
        );
      }
    }
    

    The scope model used in the form:

    import 'package:scoped_model/scoped_model.dart';
    
    import '../models/assegno.dart';
    
    class AssegnoModel extends Model{
      List <Assegno> _assegno = [];
      int _selectesAssegnoIndex;
    
      List<Assegno> get assegno{
        return List.from(_assegno);
      }
    
      int get selectesAssegnoIndex {
        return _selectesAssegnoIndex;
      }
    
      Assegno get selectedAssegno{
        if(_selectesAssegnoIndex == null){
          return null;
        }
        return _assegno[_selectesAssegnoIndex];
      }
    
      void aggiungiAssegno(Assegno assegno) {
          _assegno.add(assegno);
          _selectesAssegnoIndex = null;
        //print(_assegno);
      }
    
      void aggiornaAssegno(Assegno assegno) {
          _assegno[_selectesAssegnoIndex] = assegno;
          _selectesAssegnoIndex = null;
      }
    
      void eliminaAssegno() {
          _assegno.removeAt(_selectesAssegnoIndex);
          _selectesAssegnoIndex = null;
      }
    
      void selectAssegno(int index){
        _selectesAssegnoIndex = index;
      }
    }
    
    • Incorporeal Logic
      Incorporeal Logic over 5 years
      I don't believe this should have the [java] tag, Sabatin. Flutter uses Dart, which is all that you have included here.