Passing Flutter Text Field data into parent widget

1,568

Solution 1

Full working code:

Add

final Function(String) onChange;

to TextFieldContainer1

Add

onChanged: widget.onChange,

to TextField (and remove Controller)

Add

onChange: (val) => setState(() {
                          soldPrice = double.parse(val);
                          print(val);
                        })

to TextFieldContainer1 call in Calculator.

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(child: Calculator()),
      ),
    );
  }
}

Color BgColor = Colors.white;
Color YellowBg = Colors.yellow;
Color tileBackground = Colors.black;

class Calculator extends StatefulWidget {
  @override
  _CalculatorState createState() => _CalculatorState();
}

class _CalculatorState extends State<Calculator> {

  double soldPrice=0.00;

  void printSoldPrice(){
    print(soldPrice);
  }



  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: BgColor ,
      bottomNavigationBar: Container(
        decoration: BoxDecoration(
          borderRadius:BorderRadius.only(topLeft: Radius.circular(10), topRight:Radius.circular(10) ),
          color:YellowBg,
        ),
        alignment: Alignment.center,
        height: 50,

        child: Text('RESET',
        style: TextStyle(
          fontSize: 20,
          fontWeight: FontWeight.w500,
          letterSpacing: 5,

        ),
        ),
      ),

      body: SafeArea(
              child: Column(
          children: <Widget>[
            SizedBox(height:10),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                FlutterLogo(size: 30,),  
              ],
            ),
            SizedBox(height:10),


            Padding(
              padding:EdgeInsets.symmetric(horizontal:10.0),
              child:FractionallySizedBox(
                widthFactor: 0.9,
                child: Container(
                height:1.0,
                width:130.0,
                color:Colors.white,),
              ),),

            SizedBox(height: 10,),

            Expanded(
              child:ListView(
                children: <Widget>[

                  TextFieldContainer1(
                    title: 'SOLD PRICE',
                    tagLine: "SALE PRICE WITOHUT SHIPPING",
                    icon: Icons.check_circle,

                    onChange: (val) => setState(() {
                      soldPrice = double.parse(val);
                      print(val);
                    })
                  ),

                ],
            )),
            Text("$soldPrice")

          ],
        ),
      )

    );
  }
}

class TextFieldContainer1 extends StatefulWidget {
  final String title;
  final String tagLine;
  final IconData icon;

  final Function(String) onChange;

  TextFieldContainer1({this.title,this.tagLine,this.icon, this.onChange});


  @override
  _TextFieldContainer1State createState() => _TextFieldContainer1State();
}

class _TextFieldContainer1State extends State<TextFieldContainer1> {

  @override
  Widget build(BuildContext context) {



    return FractionallySizedBox(
      widthFactor: 0.95,
        child: Container(

          padding: EdgeInsets.symmetric(horizontal:20, vertical:5),
          decoration: BoxDecoration(
            borderRadius: BorderRadius.all(Radius.circular(10)),
            color: tileBackground,
          ),                      
          height: 57,
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children:<Widget>[
              Container(
                child:Column(

                  children:<Widget>[
                    Row(

                      children:<Widget>[
                        Icon(widget.icon,
                        color: Colors.white,
                        size:27.5
                        ),
                        SizedBox(width:5),
                        Text(widget.title,
                        style: TextStyle(

                          fontSize: 20,
                          color:Colors.white,
                          fontWeight: FontWeight.w500
                        ),
                        )
                      ]          
                    ),
                    Text(widget.tagLine,
                    style: TextStyle(
                      color:Color.fromRGBO(255, 255, 255, 0.5),
                      fontSize: 12
                    ),
                    )
                  ]
                )
              ),
              Container(
                padding: EdgeInsets.symmetric(horizontal: 15,vertical: 5),
                decoration: BoxDecoration(
                  color: Color.fromRGBO(252, 205, 0, 0.2),
                  borderRadius: BorderRadius.all(Radius.circular(10)
                  )
                ),
                height: 40,
                width: 92,
                child: TextField(
                  textAlign: TextAlign.center,
                  style: TextStyle(
                    color: Colors.white,
                    fontSize: 20
                  ),
                  autofocus: false,
                  decoration:InputDecoration( 
                    focusColor: YellowBg,
                    fillColor: YellowBg,
                    hoverColor: YellowBg,
                    enabledBorder: UnderlineInputBorder(
                      borderSide: BorderSide(color: YellowBg),
                    ),
                    focusedBorder: UnderlineInputBorder(
                      borderSide: BorderSide(color: YellowBg),)
                  ) ,
                  keyboardType: TextInputType.number,
                  onChanged: widget.onChange,
                ),
              )
            ],
          ),

      ),
    );
  }
}

Solution 2

It is pretty simple to create the custom class for textField. Below are the two steps to achieve this. First step is to create the stateful widget for text field.

 RCTextField({
@required this.hintText,
@required this.labelText,
@required this.prefixIcon,
@required this.suffixIcon,
@required this.kType,
@required this.kAction,
@required this.validatorFunction,
@required this.onChange,
});

final String hintText;
final String labelText;
final String prefixIcon;
final String suffixIcon;
final TextInputType kType;
final TextInputAction kAction;
final Function validatorFunction;
final Function(String) onChange;

@override
_RCTextFieldState createState() => _RCTextFieldState();
}

class _RCTextFieldState extends State<RCTextField> {
FocusNode myFocusNode;

get validatorFunction => null;
get textFieldValue => null;
get onChange => null;
@override
void initState() {
  super.initState();
  myFocusNode = FocusNode();
  myFocusNode.addListener(_onOnFocusNodeEvent);
}

_onOnFocusNodeEvent() {
  setState(() {
    // Re-renders
  });
}

@override
void dispose() {
  // Clean up the focus node when the Form is disposed.
  myFocusNode.dispose();
  super.dispose();
}

@override
Widget build(BuildContext context) {
  return Container(
    // margin: EdgeInsets.fromLTRB(20, 20, 20, 0),
    child: TextFormField(
    onEditingComplete: () => FocusScope.of(context).nextFocus(),
    textInputAction: widget.kAction,
    cursorColor: Colors.black,
    style: new TextStyle(color: _getInputTextColor()),
    focusNode: myFocusNode,
    validator: validatorFunction,
    decoration: InputDecoration(
      // focusColor: Colors.red,
      // fillColor: Colors.blueGrey,
      enabledBorder: UnderlineInputBorder(
        borderSide: BorderSide(color: kInactiveTextFieldColour),
      ),
      focusedBorder: UnderlineInputBorder(
        borderSide: BorderSide(color: kActiveTextFieldColour),
      ),
      border: UnderlineInputBorder(),
      filled: false,
      prefixIcon: Padding(
        padding: EdgeInsets.all(14.0),
        child: SvgPicture.asset(
          'images/' + widget.prefixIcon + '.svg',
          semanticsLabel: 'Acme Logo',
          color: myFocusNode.hasFocus
              ? kActiveTextFieldColour
              : kInactiveTextFieldColour,
        ),
      ),
      hintText: widget.hintText,
      labelText: widget.labelText,
      labelStyle: TextStyle(
          color: myFocusNode.hasFocus
              ? kActiveTextFieldColour
              : kInactiveTextFieldColour),
    ),
    keyboardType: widget.kType,
    onChanged: widget.onChange,
  ),
);
}

Color _getInputTextColor() {
return myFocusNode.hasFocus ? Colors.black : Colors.black;
}
}

Below is the next end to last step to use this class.

RCTextField(
            hintText: 'Enter your text',
            labelText: 'Text',
            prefixIcon: 'plus',
            suffixIcon: null,
            kType: TextInputType.visiblePassword,
            kAction: TextInputAction.done,
            onChange: (val) => setState(() {
              print(val);
            }),
          ),

Let me know if you find any trouble.

Share:
1,568
Pasan Madhushan
Author by

Pasan Madhushan

Updated on December 20, 2022

Comments

  • Pasan Madhushan
    Pasan Madhushan over 1 year

    How to use child widget text field data from parent widget.

    I am developing a calculator type flutter application. I want to

    This is the main calculator class

    class Calculator extends StatefulWidget {
      @override
      _CalculatorState createState() => _CalculatorState();
    }
    
    class _CalculatorState extends State<Calculator> {
    
      double soldPrice=0.00;
     
      void printSoldPrice(){
        print(soldPrice);
      }
      
     
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          backgroundColor: BgColor ,
          bottomNavigationBar: Container(
            decoration: BoxDecoration(
              borderRadius:BorderRadius.only(topLeft: Radius.circular(10), topRight:Radius.circular(10) ),
              color:YellowBg,
            ),
            alignment: Alignment.center,
            height: 50,
            
            child: Text('RESET',
            style: TextStyle(
              fontSize: 20,
              fontWeight: FontWeight.w500,
              letterSpacing: 5,
    
            ),
            ),
          ),
    
          body: SafeArea(
                  child: Column(
              children: <Widget>[
                SizedBox(height:10),
                Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    EcalLogo(logoSize: 30,),  
                  ],
                ),
                SizedBox(height:10),
             
                
                Padding(
                  padding:EdgeInsets.symmetric(horizontal:10.0),
                  child:FractionallySizedBox(
                    widthFactor: 0.9,
                    child: Container(
                    height:1.0,
                    width:130.0,
                    color:Colors.white,),
                  ),),
    
                SizedBox(height: 10,),
    
                Expanded(
                  child:ListView(
                    children: <Widget>[
    
                      TextFieldContainer1(
                        title: 'SOLD PRICE',
                        tagLine: "SALE PRICE WITOHUT SHIPPING",
                        icon: Icons.check_circle,
                        
                    
                      ),
            
                    ],
                ))
    
    
              ],
            ),
          )
          
        );
      }
    }
    
    
    
    

    This is the child TextFieldContainer1 class

    class TextFieldContainer1 extends StatefulWidget {
      final String title;
      final String tagLine;
      final IconData icon;
      
      
      
      TextFieldContainer1({this.title,this.tagLine,this.icon});
    
    
      @override
      _TextFieldContainer1State createState() => _TextFieldContainer1State();
    }
    
    class _TextFieldContainer1State extends State<TextFieldContainer1> {
    
      final controller1 = TextEditingController();
    
    
      
    
      @override
      Widget build(BuildContext context) {
        return FractionallySizedBox(
          widthFactor: 0.95,
            child: Container(
             
              padding: EdgeInsets.symmetric(horizontal:20, vertical:5),
              decoration: BoxDecoration(
                borderRadius: BorderRadius.all(Radius.circular(10)),
                color: tileBackground,
              ),                      
              height: 57,
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children:<Widget>[
                  Container(
                    child:Column(
                      
                      children:<Widget>[
                        Row(
                          
                          children:<Widget>[
                            Icon(widget.icon,
                            color: Colors.white,
                            size:27.5
                            ),
                            SizedBox(width:5),
                            Text(widget.title,
                            style: TextStyle(
                              
                              fontSize: 20,
                              color:Colors.white,
                              fontWeight: FontWeight.w500
                            ),
                            )
                          ]          
                        ),
                        Text(widget.tagLine,
                        style: TextStyle(
                          color:Color.fromRGBO(255, 255, 255, 0.5),
                          fontSize: 12
                        ),
                        )
                      ]
                    )
                  ),
                  Container(
                    padding: EdgeInsets.symmetric(horizontal: 15,vertical: 5),
                    decoration: BoxDecoration(
                      color: Color.fromRGBO(252, 205, 0, 0.2),
                      borderRadius: BorderRadius.all(Radius.circular(10)
                      )
                    ),
                    height: 40,
                    width: 92,
                    child: TextField(
                      textAlign: TextAlign.center,
                      style: TextStyle(
                        color: Colors.white,
                        fontSize: 20
                      ),
                      autofocus: false,
                      decoration:InputDecoration( 
                        focusColor: YellowBg,
                        fillColor: YellowBg,
                        hoverColor: YellowBg,
                        enabledBorder: UnderlineInputBorder(
                          borderSide: BorderSide(color: YellowBg),
                        ),
                        focusedBorder: UnderlineInputBorder(
                          borderSide: BorderSide(color: YellowBg),)
                      ) ,
                      keyboardType: TextInputType.number,
                      controller: controller1,
                      
                     
                    ),
                  )
                ],
              ),
    
          ),
        );
      }
    }
    
    
    
    

    I want to use the controller1 data (data from text field) in TextFieldContainer1 class to update the soldPrice variable in calculator class and simply print it when textField onChanged has triggered. How to do that?

  • Pasan Madhushan
    Pasan Madhushan about 4 years
    Now it works fine. It is the correct method to pass text field data to parent widget. Thank you
  • Manoj Perumarath
    Manoj Perumarath about 3 years
    how to update the text from a parent widget/ screen?
  • hewa jalal
    hewa jalal about 3 years
    i am not sure what you mean, please create a question on stack overflow.