Pasan Madhushan
Pasan Madhushan

Reputation: 255

Passing Flutter Text Field data into parent widget

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?

Upvotes: 3

Views: 2971

Answers (3)

shubham
shubham

Reputation: 631

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.

Upvotes: 2

camillo777
camillo777

Reputation: 2367

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,
                ),
              )
            ],
          ),

      ),
    );
  }
}

Upvotes: 3

hewa jalal
hewa jalal

Reputation: 963

make the text field class constructor accept a function, then use that function in onChange like below:

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

class _TextFieldContainer1State extends State<TextFieldContainer1> {

  final controller1 = TextEditingController();
  final Function onChange;



  @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
                  ),
                  onChange: widget.onChange,
                  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,


                ),
              )
            ],
          ),

      ),
    );
  }
}

now when you use it in calculator class you use it like this:

TextFieldContainer1(
                    title: 'SOLD PRICE',
                    tagLine: "SALE PRICE WITOHUT SHIPPING",
                    icon: Icons.check_circle,
                    onChanga: (value) => print(value);
// now you have access to your text field value inside your calculator class
                  ),

you may also want to make your text field class Stateless as you are not using setState anywhere.

Upvotes: 0

Related Questions