2017-09-22 3 views
2

J'ai un problème étrange dans mon application J'ai une page d'inscription avec plusieurs champs de texte dans un ListView et le ListView est un enfant au Formulaire. Lorsque j'atteins le dernier champ de formulaire dans ListView, je dois faire défiler l'écran pour voir ce que je saisis dans le champ. Quand je fais défiler vers le haut les champs de texte qui sont flous perdent le texte entré et sont initialisés comme nul. Je ne suis pas sûr de ce que je suis manquant ou dois-je utiliser d'une autre manière pour m'assurer que je conserve les valeurs TextFormField. J'ai essayé d'utiliser le contrôleur dans chaque TextFormField puis il conserve la valeur même si je défile vers le haut. Mais, les propriétés de l'objet, par exemple hostelData.hostelName, ne sont mises à jour que la première fois et les modifications ne sont pas reflétées dans la propriété d'objet à partir de la deuxième fois. Je ne suis pas si sûr de ce que je manque? S'il vous plaît, quelqu'un peut-il m'aider à résoudre ce problème? S'il vous plaît excuser mes erreurs dans l'affichage comme je suis nouveau à la programmation et toute aide serait grandement appréciée.La valeur de TextFormField n'est pas mise à jour comme prévu dans flutter

J'ai posté le code ci-dessous afin que vous puissiez reproduire le même problème.

import 'dart:async'; 

import 'package:firebase_auth/firebase_auth.dart'; 
import 'package:firebase_database/firebase_database.dart'; 
import 'package:flutter/material.dart'; 
import 'package:flutter/rendering.dart'; 
import 'package:flutter/widgets.dart';  
import 'package:myhostel/theme.dart' as Theme; 
import 'package:myhostel/globals.dart' as gl; 

class SignUp extends StatefulWidget { 
const SignUp({ Key key }) : super(key: key); 
@override 
    _SignUpState createState() => new _SignUpState(); 
    } 

class HostelData{ 
String hostelName = ''; 
String ownersName = ''; 
String mobileNumber = ''; 
String emailId = ''; 
String password = ''; 
String city = ''; 
String hostelType= 'mens'; 
String confirmPassword =''; 
} 
class _SignUpState extends State<SignUp> { 
HostelData hostelData = new HostelData(); 

void showInSnackBar(String value) { 
_scaffoldKey.currentState.showSnackBar(new SnackBar(
    content: new Text(value), 
    duration: const Duration(milliseconds: 3000), 

)); 
} 

final GlobalKey<FormState> _formKey = new GlobalKey<FormState>(); 
final GlobalKey<FormFieldState<String>> _passwordFieldKey = new 
GlobalKey<FormFieldState<String>>(); 
bool _autovalidate = false; 
bool _formWasEdited = false; 

void _handleSubmitted() { 
    final FormState form = _formKey.currentState; 
if (!form.validate()) { 
    _autovalidate = true; // Start validating on every change. 
    showInSnackBar('Please fix the errors in red before submitting.'); 
    } else { 
    form.save(); 
     showInSnackBar('${hostelData.ownersName}\'s hostel name is 
      ${hostelData.hostelName}'); 
      _createuserwithemailandpassword(); 
    } 
    } 
    String _validateName(String value) { 
    _formWasEdited = true; 
    if (value.isEmpty) 
    return 'Name is required.'; 
    final RegExp nameExp = new RegExp(r'^[A-Za-z ]+$'); 
    if (!nameExp.hasMatch(value)) 
    return 'Please enter only alphabetical characters and spaces.'; 
    return null; 
    } 
    String _validatePassword(String value) { 
     _formWasEdited = true; 
     final FormFieldState<String> passwordField = 
     _passwordFieldKey.currentState; 
    if (passwordField.value == null || passwordField.value.isEmpty) 
    return 'Please choose a password.'; 
    if (passwordField.value != value) 
    return 'Passwords don\'t match'; 
    return null; 
     } 
    @override 
    Widget build(BuildContext context){ 

    return new MaterialApp(
    theme: Theme.MyHostelThemeData, 
    home: new Scaffold(
    key: _scaffoldKey, 

    body: new Container(
     child: new Container(
     decoration: new BoxDecoration(
      image: new DecorationImage(
       image: new AssetImage('assets/bg.png'), 
      fit: BoxFit.fill, 
     ), 
    ), 
     child: new Form(

     key: _formKey, 
     autovalidate: _autovalidate, 


     child: new ListView(
     children: <Widget>[ 
      new Container(
      margin: const EdgeInsets.only(top:32.0), 
      child: new Center(
       child: new Text('SIGN UP', 
       style: new TextStyle(
        color: const Color(0xFFF5FEFD),fontSize:24.0,fontWeight: 
      FontWeight.bold), 
      ), 
     ), 
     ), 
     new Row(
      children:[ 


     new Expanded(
     child: new Container(
     margin: const EdgeInsets.only(left: 24.0,right: 12.0,), 

     child:new TextFormField(decoration: new InputDecoration(
      /*hintStyle: new TextStyle(
       fontSize: 20.0,color: const Color(0xFFF5FEFD),),*/ 
      labelText: 'Hostel Name', 
     ), 
      /*style: new TextStyle(
      fontSize: 20.0, 
      color: Colors.white, 
     ),*/ 

      onSaved:(String value){ hostelData.hostelName = value; }, 
      validator: _validateName, 
     ), 
     ), 
    ), 
    ], 
    ), 
    new Row(
      children:[ 
       /*new Container(
       margin: const EdgeInsets.all(8.0), 
       width: 24.0, 
       child: new Image.asset(
        'assets/person_avatar.png', 
        fit: BoxFit.contain, 
        //alignment: FractionalOffset.center, 
       ), 
      ),*/ 

       new Expanded(
       child: new Container(
        margin: const EdgeInsets.only(left: 24.0,right: 12.0,), 

        child:new TextFormField(
        //controller: _ownersNameController, 

        decoration: new InputDecoration(//hintText: 'Mobile 
      Number', 
        /* hintStyle: new TextStyle(fontSize: 20.0,color: const 
      Color(0xFFF5FEFD),),*/ 
         labelText: 'Owners Name', 
        ), 

        /*style: new TextStyle(
         fontSize: 20.0, 
         color: Colors.white, 
        ),*/ 
       onSaved: (String value) { hostelData.ownersName = value; 
                     }, 
        validator: _validateName, 
       ), 
       ), 
      ), 
      ], 
     ), 
     new Row(
      children:[ 



       new Expanded(
       child: new Container(
        margin: const EdgeInsets.only(left: 24.0,right: 12.0,), 

        child:new TextFormField(
        //controller: _mobileNumberController, 
        keyboardType: TextInputType.phone, 

        decoration: new InputDecoration(//hintText: 'Mobile 
        Number', 
         /* hintStyle: new TextStyle(fontSize: 20.0,color: 
         const Color(0xFFF5FEFD),),*/ 
         labelText: 'Mobile Number', 
         //prefixText: '+91', 
        ), 

        /*style: new TextStyle(
         fontSize: 20.0, 
         color: Colors.white, 
        ),*/ 
       onSaved: (String value) { hostelData.mobileNumber = value; }, 
        //validator: _validatePhoneNumber, 
       ), 
       ), 
      ), 
      ], 
     ), 
     //implements EmailID Row 
      new Row(
      children:[ 


       new Expanded(
       child: new Container(
        margin: const EdgeInsets.only(left: 24.0,right: 12.0,), 

        child:new TextFormField(
        //controller: _emailIdController, 

        decoration: new InputDecoration(
         //hintText: 'Mobile Number', 
         /*hintStyle: new TextStyle(fontSize: 20.0,color: const 
          Color(0xFFF5FEFD),),*/ 
         labelText: 'EMail Id', 
         helperText: 'Required', 
        ), 
        /*style: new TextStyle(
         fontSize: 20.0, 
         color: Colors.white, 
        ),*/ 
        onSaved: (String value){hostelData.emailId = value;}, 
       ), 
       ), 
      ), 
      ], 
     ), 
     //implements the password row 

      new Container(
      padding: const EdgeInsets.only(left: 8.0,), 
      child: new Row(
       children: <Widget>[ 
       new Container(
        margin: const EdgeInsets.only(top: 16.0), 
        //padding: const EdgeInsets.all(8.0), 
        child: new Icon(Icons.lock_outline, 
         color: const Color(0xFFF5FEFD) 
       ), 
       ), 
       new Expanded(
        child: new Container(
        margin: const EdgeInsets.only(
         left: 28.0, right: 12.0,), 
        child: new TextFormField(
         key: _passwordFieldKey, 
         //controller: _passwordController, 
         decoration: const InputDecoration(
         hintText: 'min 8 characters', 
         labelText: 'Password', 
          helperText: 'Required', 

        ), 
         autocorrect: false, 
         //obscureText: true, 
         //validator: 'Required', 
         /*style: DefaultTextStyle.of(context).style.merge(new 
             TextStyle(
           fontSize: 16.0, 
           color: CustomColors.fontColor, 
          ), 
          ),*/ 
         onSaved: (String value){hostelData.password = value;}, 

        ), 
       ), 
       ), 
       ], 
      ), 
     ), 
      new Container(
      padding: const EdgeInsets.only(left: 8.0,), 
      child: new Row(
       children: <Widget>[ 
       new Container(
        margin: const EdgeInsets.only(top: 16.0), 
        //padding: const EdgeInsets.all(8.0), 
        child: new Icon(Icons.lock_outline, 
         color: const Color(0xFFF5FEFD) 
       ), 
       ), 
       new Expanded(
        child: new Container(
        margin: const EdgeInsets.only(
         left: 28.0, right: 12.0,), 
        child: new TextFormField(
         //controller: _confirmpasswordcontroller, 
         decoration: const InputDecoration(
         labelText: 'Confirm Password', 
         helperText: 'Required' 


        ), 
         autocorrect: false, 
        // obscureText: true, 
         //validator: 'Required', 
         /*style: DefaultTextStyle.of(context).style.merge(new 
        TextStyle(
           fontSize: 16.0, 
           color: CustomColors.fontColor, 
          ), 
          ),*/ 
         //onSaved: (String value){hostelData.confirmPassword = 
               value;}, 

         validator: _validatePassword, 
        ), 
       ), 
       ), 
       ], 
      ), 
     ), 
      new Row(
      children:[ 

       new Expanded(
       child: new Container(
        margin: const EdgeInsets.only(left: 24.0,right: 12.0,), 

        child:new TextFormField(
        controller: _cityController, 

        decoration: new InputDecoration(labelText: 'City*'), 

        onSaved: (String value){hostelData.city = value;}, 
        validator: _validateName, 
       ), 
       ), 
      ), 
      ], 
     ), 
     new Container(
      padding: const EdgeInsets.all(8.0), 
      margin: const EdgeInsets.only(left:24.0,right: 24.0), 
      decoration: new BoxDecoration(
       border: new Border.all(
       color: Colors.white, 
       width: 2.0, 
      ), 
       borderRadius: new BorderRadius.all(const 
        Radius.circular(32.0),) 
      ), 
     child: new FlatButton(
      onPressed: ((){ 
      print('SignUp Button Clicked'); 
      _handleSubmitted(); 
      }), 
      child: new Text (
      'SIGN UP', 
      style: new TextStyle(fontSize: 24.0, 
       fontWeight: FontWeight.bold, 
       color: Colors.white, 
      ), 
     ), 
     ), 
     ), 
      new Row(
      children:[ 


       new Container(
        margin: const EdgeInsets.only(left: 24.0,bottom: 12.0), 

        child:new Text(
        'Already have an account?', 
         style: new TextStyle(
         fontSize: 20.0, 
         color: Colors.white, 
        ), 
       ), 
       ), 

       new Container(
       padding: const EdgeInsets.only(right: 8.0,top: 
        4.0,bottom:16.0), 
       margin: const EdgeInsets.only(right: 12.0,left: 4.0), 
       child: 
       new MaterialButton(
       onPressed: ((){ 
       //Sign In Button pressed declaration here 
       print('sign in button clicked'); 

       }), 
        child: new Text('SignIn', 
        style: new TextStyle(
        fontSize: 16.0, 
        color: Colors.teal[200], 
        ), 
        ), 
       minWidth: 16.0, 
      ), 
      ), 

      ], 
     ), 
      new Container(
      padding: const EdgeInsets.only(left: 16.0), 
      child: new Text('* indicates required field', 
       style: new TextStyle(
        fontSize: 14.0, 
        color: Colors.white, 
       ),), 
     ), 
     ] 
    ), 
     ), 
    ), 

    ), 

    ), 

    ); 

    } // widget ends here 

globals.dart

library my_hostel.globals; 

import 'package:firebase_auth/firebase_auth.dart'; 
import 'package:firebase_database/firebase_database.dart'; 



    final FirebaseAuth auth = FirebaseAuth.instance; 

final DatabaseReference messagesRef =FirebaseDatabase.instance.reference(); 
+0

Il vous manque des contrôleurs pour les champs de texte. Voici le docu sur TextEditingControllers: https://docs.flutter.io/flutter/widgets/TextEditingController-class.html Le ListView supprime les enfants qui sont hors de vue pour des raisons de performances et les ajoute à nouveau lorsqu'ils sont à nouveau visibles. Sans les contrôleurs, les champs de texte sont initialisés avec une chaîne vide. Je suis tombé comme si j'avais déjà répondu à ça. Je posterai le lien une fois que je l'aurai trouvé. –

+0

Ici, il est: https://stackoverflow.com/questions/45240734/flutter-form-data-disappears-when-i-scroll/45242235#45242235 –

+0

Merci pour votre réponse, j'ai pensé à ce sujet et j'ai réalisé que je perdais les valeurs de chaîne car je n'ai pas utilisé les contrôleurs, puis essayé avec les contrôleurs. 'Voila' cela a fonctionné, mais la joie n'a été que de courte durée car lorsque je modifie à nouveau les champs, les nouvelles valeurs ne sont pas écrites dans les champs d'objet comme dans hostelData.hostelName, hostelData.emailId etc., seule la première valeur est affectée pas les changements qui sont faits plus tard. Je suis vraiment désolé de ne pas avoir vu votre réponse précédente, mais merci beaucoup pour votre aide. – Mahi

Répondre

1

Voici un exemple de code de travail:

class MyHomePage extends StatefulWidget { 
    @override 
    _MyHomePageState createState() => new _MyHomePageState(); 
} 

class _MyHomePageState extends State<MyHomePage> { 

    String s1 = ""; 
    String s2 = ""; 
    String s3 = ""; 
    String s4 = ""; 
    String s5 = ""; 

    final TextEditingController c1 = new TextEditingController(); 
    final TextEditingController c2 = new TextEditingController(); 
    final TextEditingController c3 = new TextEditingController(); 
    final TextEditingController c4 = new TextEditingController(); 
    final TextEditingController c5 = new TextEditingController(); 

    @override 
    Widget build(BuildContext context) { 
    return new Scaffold(
     appBar: new AppBar(title: new Text("Example"),), 
     body: new ListView(
     children: <Widget>[ 
      new Padding(padding: new EdgeInsets.all(70.0),), 
      new TextField(
      controller: c1, 
      onChanged: (String text) { 
       s1 = text; 
      }, 
     ), 
      new Padding(padding: new EdgeInsets.all(70.0),), 
      new TextField(
      controller: c2, 
      onChanged: (String text) { 
       s2 = text; 
      }, 
     ), 
      new Padding(padding: new EdgeInsets.all(70.0),), 
      new TextField(
      controller: c3, 
      onChanged: (String text) { 
       s3 = text; 
      }, 
     ), 
      new Padding(padding: new EdgeInsets.all(70.0),), 
      new TextField(
      controller: c4, 
      onChanged: (String text) { 
       s4 = text; 
      }, 
     ), 
      new Padding(padding: new EdgeInsets.all(70.0),), 
      new TextField(
      controller: c5, 
      onChanged: (String text) { 
       s5 = text; 
      }, 
     ), 
     ], 
    ) 
    ); 
    } 
} 

Vous devez ajouter un TextEditingController avec votre TextField. Listview supprime les widgets invisibles, car le rendu d'une tonne de widgets qui ne sont pas affichés rendrait la performance plus mauvaise!

+0

Merci pour votre réponse, j'ai pensé à cela et j'ai réalisé que je perdais les valeurs de chaîne car je n'ai pas utilisé les contrôleurs et ensuite essayé avec les contrôleurs. 'Voila' ça marchait, mais la joie n'était que de courte durée car quand je modifie les champs les nouvelles valeurs ne sont pas écrites dans les chaînes comme dans votre cas s1, s2 etc seulement la première valeur est affectée pas les changements effectués plus tard. – Mahi

+0

Notez que j'utilise 'onChanged' dans mes' TextField's. Cette méthode 'onChanged' est déclenchée chaque fois que le texte change, donc pas seulement quand vous tapez return. Cela devrait résoudre votre problème! –

+0

Salut Bram, Merci pour votre réponse, je voulais utiliser la propriété validateur pour le champ de texte, donc je suis allé pour le TextFormField. Je vais essayer de trouver la réponse et j'espère que j'y arriverai. Je vous remercie. – Mahi