I got stuck with a problem in Flutter: The following assertion was thrown building TextField, it flesh me a stranger problem
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
Related videos on Youtube
Sabatin 02
Updated on May 26, 2022Comments
-
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 over 5 yearsI don't believe this should have the [java] tag, Sabatin. Flutter uses Dart, which is all that you have included here.
-