How can i get value from child to parent on button click when button is in parent?

169

You can copy paste run full code below
You can use GlobalKey to get deliveryState of Delivery, and use deliveryState to get attribute of Delivery, attribute here is RadioModel selected
Step 1: Use GlobalKey _key = GlobalKey();

class _MyHomePageState extends State<DeliveryTimeline> {
  ...
  GlobalKey _key = GlobalKey();

Step 2: Use deliveryState to get seleted item

onStepContinue: () {
          setState(() {
            if (this._currentStep == 0) {
              this._currentStep = this._currentStep + 1;

              final _DeliveryState deliveryState =
                  _key.currentState;
              print("hi ${deliveryState.selected.title} ${deliveryState.selected.label} ");

Step 3: Delivery need key

child: Delivery(
              key: _key,
              onShipingTypeClicked: (shippingtype) {
 ...
 Delivery({Key key, this.onShipingTypeClicked}) : super(key:key);

Step 4: Set variable selected

RadioModel selected = null;
...
return InkWell(
              onTap: () {
                setState(() {
                  ...
                  selected = sampleData[index];  

working demo

enter image description here

output of working demo

I/flutter ( 6246): hi Standard Delivery Order will be delivered between 3 - 5 business days 

full code

import 'package:flutter/material.dart';

class DeliveryTimeline extends StatefulWidget {
  DeliveryTimeline({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<DeliveryTimeline> {
  int _currentStep = 0;
  String shippingtype;
  GlobalKey _key = GlobalKey();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          backgroundColor: Colors.white,
          centerTitle: true,
          iconTheme: IconThemeData(color: Colors.black),
          elevation: 0,
          title: Text(
            "Checkout",
            style: TextStyle(color: Colors.black),
          ),
        ),
        body: Stepper(
            type: StepperType.horizontal,
            steps: _mySteps(),
            currentStep: this._currentStep,
            onStepTapped: (step) {
              setState(() {
                this._currentStep = step;
              });
            },
            onStepContinue: () {
              setState(() {
                if (this._currentStep == 0) {
                  this._currentStep = this._currentStep + 1;

                  final _DeliveryState deliveryState =
                      _key.currentState;
                  print("hi ${deliveryState.selected.title} ${deliveryState.selected.label} ");

                } else if (this._currentStep == 1) {
                  this._currentStep = this._currentStep + 1;
                } else {
                  print('Completed, check fields.');
                }
              });
            },
            onStepCancel: () {
              setState(() {
                if (this._currentStep > 0) {
                  this._currentStep = this._currentStep - 1;
                } else {
                  this._currentStep = 0;
                }
              });
            },
            controlsBuilder: (BuildContext context,
                {VoidCallback onStepContinue,
                VoidCallback onStepCancel,
                Function onShippingNextClick}) {
              return Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: <Widget>[
                  OutlineButton(
                      child: Text("Back"),
                      onPressed: onStepCancel,
                      shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(4.0))),
                  MaterialButton(
                    child: Text("Next"),
                    color: Colors.blue,
                    textColor: Colors.white,
                    onPressed: onStepContinue,
                  ),
                ],
              );
            }));
  }

  List<Step> _mySteps() {
    List<Step> _steps = [
      Step(
        title: Text('Delivery'),
        content: Center(
          child: Container(
            height: MediaQuery.of(context).size.height / 1.5,
            child: Delivery(
              key: _key,
              onShipingTypeClicked: (shippingtype) {
                shippingtype = shippingtype;
                print("myvalue${shippingtype}");
              },
            ),
          ),
        ),
        isActive: _currentStep >= 0,
      ),
      Step(
        title: Text('Address'),
        content: Text("Address()"),
        isActive: _currentStep >= 1,
      ),
      Step(
        title: Text('Payment'),
        content: Text("Payment()"),
        isActive: _currentStep >= 2,
      )
    ];
    return _steps;
  }
}

class Delivery extends StatefulWidget {
  final ValueChanged<String> onShipingTypeClicked;

  Delivery({Key key, this.onShipingTypeClicked}) : super(key:key);

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

class _DeliveryState extends State<Delivery> {
  List<RadioModel> sampleData = List<RadioModel>();

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    sampleData.add(RadioModel(false, 'A', 0xffe6194B, "Standard Delivery",
        "Order will be delivered between 3 - 5 business days", 1));
    sampleData.add(RadioModel(
        true,
        'A',
        0xffe6194B,
        "Next Day Delivery",
        "Place your order before 6pm and your items will be delivered the next day",
        2));
    sampleData.add(RadioModel(
        false,
        'A',
        0xffe6194B,
        "Nominated Delivery",
        "Pick a particular date from the calendar and order will be delivered on selected date",
        3));
  }

  RadioModel selected = null;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView.builder(
        itemCount: sampleData.length,
        shrinkWrap: true,
        physics: NeverScrollableScrollPhysics(),
        itemBuilder: (BuildContext context, int index) {
          return InkWell(
              onTap: () {
                setState(() {
                  sampleData.forEach((element) => element.isSelected = false);
                  sampleData[index].isSelected = true;
                  selected = sampleData[index];
                  widget.onShipingTypeClicked(sampleData[index].buttonText);
                });
              },
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  ListTile(
                    title: Text(sampleData[index].title),
                  ),
                  Padding(
                    padding: const EdgeInsets.only(bottom: 20.0),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceAround,
                      children: <Widget>[
                        Flexible(
                          child: Text(sampleData[index].label),
                        ),
                        RadioItem(sampleData[index]),
                      ],
                    ),
                  )
                ],
              ));
        },
      ),
    );
  }
}

class RadioItem extends StatelessWidget {
  final RadioModel _item;

  RadioItem(this._item);

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.all(15.0),
      child: Row(
        mainAxisSize: MainAxisSize.max,
        children: <Widget>[
          Container(
            height: 25.0,
            width: 25.0,
            alignment: Alignment.center,
            child: Container(
                height: 15.0,
                width: 15.0,
                decoration: BoxDecoration(
                  color: Colors.blue,
                  borderRadius:
                      const BorderRadius.all(const Radius.circular(15)),
                )),
            decoration: BoxDecoration(
              color: Colors.transparent,
              border: Border.all(
                  width: 3.0,
                  color: _item.isSelected ? Colors.blue : Colors.transparent),
              borderRadius: const BorderRadius.all(const Radius.circular(25)),
            ),
          ),
          Container(margin: EdgeInsets.only(left: 10.0))
        ],
      ),
    );
  }
}

class RadioModel {
  bool isSelected;
  final String buttonText;
  final int colorCode;
  final String title, label;
  final int buttonid;

  RadioModel(this.isSelected, this.buttonText, this.colorCode, this.title,
      this.label, this.buttonid);
}

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: DeliveryTimeline(),
    );
  }
}
Share:
169
Snofkin Suwal
Author by

Snofkin Suwal

Updated on December 23, 2022

Comments

  • Snofkin Suwal
    Snofkin Suwal over 1 year

    I have been using Stepper view by flutter.And I am having an issue on getting value from child to parent on button click as the button is in parent widget.

    Here is my Parent class and my child class.

    Parent Class This is my parent class which has a Stepper view with next and back button.I want to get value from my child class to parent class when next button is clicked.

       class DeliveryTimeline extends StatefulWidget {
          DeliveryTimeline({Key key, this.title}) : super(key: key);
        
          final String title;
        
          @override
          _MyHomePageState createState() => new _MyHomePageState();
        }
        
        class _MyHomePageState extends State<DeliveryTimeline> {
          int _currentStep = 0;
          String shippingtype;
        
          @override
          Widget build(BuildContext context) {
            return new Scaffold(
                appBar: AppBar(
                  backgroundColor: Colors.white,
                  centerTitle: true,
                  iconTheme: new IconThemeData(color: Colors.black),
                  elevation: 0,
                  title: Text(
                    "Checkout",
                    style: TextStyle(color: Colors.black),
                  ),
                ),
                body: Stepper(
                    type: StepperType.horizontal,
                    steps: _mySteps(),
                    currentStep: this._currentStep,
                    onStepTapped: (step) {
                      setState(() {
                        this._currentStep = step;
                      });
                    },
                    onStepContinue: () {
                      setState(() {
                        if (this._currentStep == 0) {
                          this._currentStep = this._currentStep + 1;
    
    **//need to get value here on first next click**
    
                        } else if (this._currentStep == 1) {
                          this._currentStep = this._currentStep + 1;
                        } else {
                          print('Completed, check fields.');
                        }
        
                      });
                    },
                    onStepCancel: () {
                      setState(() {
                        if (this._currentStep > 0) {
                          this._currentStep = this._currentStep - 1;
                        } else {
                          this._currentStep = 0;
                        }
                      });
                    },
                    controlsBuilder: (BuildContext context,
                        {VoidCallback onStepContinue,
                        VoidCallback onStepCancel,
                        Function onShippingNextClick}) {
                      return Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        children: <Widget>[
                          OutlineButton(
                              child: new Text("Back"),
                              onPressed: onStepCancel,
                              shape: new RoundedRectangleBorder(
                                  borderRadius: new BorderRadius.circular(4.0))),
                          MaterialButton(
                            child: Text("Next"),
                            color: AppColors.primarycolor,
                            textColor: Colors.white,
                            onPressed: onStepContinue,
                          ),
                        ],
                      );
                    }));
          }
        
          List<Step> _mySteps() {
            List<Step> _steps = [
              Step(
                title: Text('Delivery'),
                content: Center(
                  child: Container(
                    height: MediaQuery.of(context).size.height / 1.5,
                    child: Delivery(onShipingTypeClicked: (shippingtype){
                      shippingtype = shippingtype;
                      print("myvalue${shippingtype}");
                    },),
                  ),
                ),
                isActive: _currentStep >= 0,
              ),
              Step(
                title: Text('Address'),
                content: Address(),
                isActive: _currentStep >= 1,
              ),
              Step(
                title: Text('Payment'),
                content: Payment(),
                isActive: _currentStep >= 2,
              )
            ];
            return _steps;
          }
        
        
        }
    

    Child Class This is my child class i have a Listview which act like a radio button.I want the selected item and its value to the parent class when button is clicked..

    class Delivery extends StatefulWidget {
      final ValueChanged<String> onShipingTypeClicked;
    
       Delivery({this.onShipingTypeClicked});
    
      @override
      _DeliveryState createState() => _DeliveryState();
    }
    
    class _DeliveryState extends State<Delivery> {
    
      List<RadioModel> sampleData = new List<RadioModel>();
    
    
    
    
      @override
      void initState() {
        // TODO: implement initState
        super.initState();
        sampleData.add(new RadioModel(false, 'A', 0xffe6194B, "Standard Delivery",
            "Order will be delivered between 3 - 5 business days", 1));
        sampleData.add(new RadioModel(
            true,
            'A',
            0xffe6194B,
            "Next Day Delivery",
            "Place your order before 6pm and your items will be delivered the next day",
            2));
        sampleData.add(new RadioModel(
            false,
            'A',
            0xffe6194B,
            "Nominated Delivery",
            "Pick a particular date from the calendar and order will be delivered on selected date",
            3));
    
    
      }
    
      @override
      Widget build(BuildContext context) {
        return new Scaffold(
          body: new ListView.builder(
            itemCount: sampleData.length,
            shrinkWrap: true,
            physics: NeverScrollableScrollPhysics(),
            itemBuilder: (BuildContext context, int index) {
              return new InkWell(
                  onTap: () {
                    setState(() {
                      sampleData.forEach((element) => element.isSelected = false);
                      sampleData[index].isSelected = true;
                      widget.onShipingTypeClicked(sampleData[index].buttonText);
                    });
                  },
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget>[
                      TextSmallTitleSize(
                        title: sampleData[index].title,
                      ),
                      Padding(
                        padding: const EdgeInsets.only(bottom: 20.0),
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.spaceAround,
                          children: <Widget>[
                            Flexible(
                              child: TextSmallDimText(sampleData[index].label),
                            ),
                            RadioItem(sampleData[index]),
                          ],
                        ),
                      )
                    ],
                  ));
            },
          ),
        );
      }
    }
    
    class RadioItem extends StatelessWidget {
      final RadioModel _item;
    
      RadioItem(this._item);
    
      @override
      Widget build(BuildContext context) {
        return new Container(
          margin: new EdgeInsets.all(15.0),
          child: new Row(
            mainAxisSize: MainAxisSize.max,
            children: <Widget>[
              new Container(
                height: 25.0,
                width: 25.0,
                alignment: Alignment.center,
                child: Container(
                    height: 15.0,
                    width: 15.0,
                    decoration: new BoxDecoration(
                      color: AppColors.primarycolor,
                      borderRadius:
                          const BorderRadius.all(const Radius.circular(15)),
                    )),
                decoration: new BoxDecoration(
                  color: Colors.transparent,
                  border: new Border.all(
                      width: 3.0,
                      color: _item.isSelected
                          ? AppColors.primarycolor
                          : Colors.transparent),
                  borderRadius: const BorderRadius.all(const Radius.circular(25)),
                ),
              ),
              new Container(margin: new EdgeInsets.only(left: 10.0))
            ],
          ),
        );
      }
    }
    
    class RadioModel {
      bool isSelected;
      final String buttonText;
      final int colorCode;
      final String title, label;
      final int buttonid;
    
      RadioModel(this.isSelected, this.buttonText, this.colorCode, this.title,
          this.label, this.buttonid);
    }
    
  • Snofkin Suwal
    Snofkin Suwal over 3 years
    Thanks @chunhunghan that really works Save my day..