3

Parent Widget

class _FamilyListPageState extends State<FamilyListPage> {
  String initialValue = 'Search Families';

  void eraseInitialValue() {     <-------------- This function is passed down to the child widget
    setState(() {
      initialValue = '';
      print('Inside the set state');    <-------- This line gets executed.
    });
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        appBar: AppBar(
          title: Text('Search Families'),
          centerTitle: true,
        ),
        backgroundColor: StaticEntry.backColor,
        body: Center(
          child: FractionallySizedBox(
            widthFactor: 0.8,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                SearchInput(   <----------------------------------------- Child Widget
                  initialValue: initialValue,
                  onTapHandler: eraseInitialValue,
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

Child Widget

import 'package:flutter/material.dart';

class SearchInput extends StatelessWidget {
  final String initialValue;
  final Function onTapHandler;      <----------- Function from the parent widget is stored in here

  SearchInput({this.initialValue, this.onTapHandler});

  @override
  Widget build(BuildContext context) {
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: ListTile(
          leading: Icon(
            Icons.search,
            size: 40,
          ),
          title: Container(
            child: TextFormField(
              initialValue: initialValue,
              textAlign: TextAlign.center,
              style: TextStyle(
                  color: Colors.grey,
                  fontWeight: FontWeight.bold,
                  fontFamily: 'Poppins',
                  letterSpacing: 1),
              onTap: onTapHandler,         <--------------- This is where I have made a pointer at the function received from the parent widget to be executed when tapped.
            ),
          ),
        ),
      ),
    );
  }
}

Background

I have a child widget which holds a TextFormField. The initialValue of that TextFormField is 'Search Families'. I am trying to erase that initial value when the user taps on that TextFormField so the user can type what he/she wants in that TextFormField without erasing it manually by themselves.

What I have done

To achieve this I have made my parent widget a stateful widget. State of my parent widget has an instance variable called initialValue that holds the value 'Search Families' which is used to configure the initialValue property of the TextFormField inside the child widget.

Then I have defined a method inside the parent widget called eraseInitialValue which resets the value of the initialValue instance variable to an empty string by calling the setState.

Finally inside the child widget, I am giving a pointer at this function for the onTap property of the TextFormField to execute the declared function which in turn should update the state of the application.

Problem

However, the text 'Search Families' never changes.

(I added a print statement inside the setState to see if the function holding the setState gets executed. It indeed does. But the state is not updated.)

Can someone help me understand this code is not working? Thanks.

CodeR_Ax20
  • 91
  • 1
  • 8

2 Answers2

0

onTapHandler() instead onTapHandler in SearchInput class

novol
  • 832
  • 4
  • 20
0

have you tried using GestureDetector? Please update your code and give feedback.

Parent Widget

class _FamilyListPageState extends State<FamilyListPage> {
  String initialValue = 'Search Families';

  void eraseInitialValue() {     <-------------- This function is passed down to the child widget
    setState(() {
      initialValue = '';
      print('Inside the set state');    <-------- This line gets executed.
    });
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        appBar: AppBar(
          title: Text('Search Families'),
          centerTitle: true,
        ),
        backgroundColor: StaticEntry.backColor,
        body: Center(
          child: FractionallySizedBox(
            widthFactor: 0.8,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                GestureDetector(
                  onTap: () { eraseInitialValue(); },
                  child: SearchInput( <----------------------------------------- Child Widget
                    initialValue: initialValue,
                    //onTapHandler: eraseInitialValue,
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

Child Widget

import 'package:flutter/material.dart';

class SearchInput extends StatelessWidget {
  final String initialValue;
  final Function onTapHandler;      <----------- Function from the parent widget is stored in here

  SearchInput({this.initialValue, this.onTapHandler});

  @override
  Widget build(BuildContext context) {
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: ListTile(
          leading: Icon(
            Icons.search,
            size: 40,
          ),
          title: Container(
            GestureDetector(
              onTap: () { onTapHandler(); },
              child: TextFormField(
                initialValue: initialValue,
                textAlign: TextAlign.center,
                style: TextStyle(
                  color: Colors.grey,
                  fontWeight: FontWeight.bold,
                  fontFamily: 'Poppins',
                  letterSpacing: 1),
              ),
            ),
          ),
        ),
      ),
    );
  }
}
  • I tried this. But still the result is the same. I also tried wrapping the parent widget with a `GestureDetector` and calling the `eraseInitialValue` function from there. But still no luck..... – CodeR_Ax20 Sep 17 '21 at 15:01
  • Create a simple class that will do a `print("It worked so far");` Call this function in the `onTap` method and see if it was at least print – Jessé Lopes Pereira Sep 17 '21 at 15:53
  • I tried what you said. The print `"It works so far works!"`. Also even in the class I had (not the test class we created now), when I add a print statement inside that function, upon tapping on the child widget, that print function is executed. It is only that the state is not updated! – CodeR_Ax20 Sep 17 '21 at 16:03
  • Anyone got answer for this? I'm having similar problem: https://stackoverflow.com/questions/70235200/flutter-callback-function-not-called-while-trying-to-call-setstate-from-child – Younghak Jang Dec 06 '21 at 00:36