Home > OS >  Why does the text disappear from the text field after clicking Done in flutter?
Why does the text disappear from the text field after clicking Done in flutter?

Time:09-15

I have a text field where the user enters text. But I ran into a problem when I enter text and press the Done button - the text disappears from the text field as if it never existed. But when the field is active and I enter characters, everything is visible. Why does the text disappear from the text field after clicking the Done button?

    class CommentWidget extends StatelessWidget {
  final Function(String) onChanged;
  final String? textForm;
  final bool isHelpPage;
  CommentWidget({Key? key, required this.onChanged, required this.textForm, required this.isHelpPage})
      : super(key: key);

  final TextEditingController controller = TextEditingController();
  String value = '';

  @override
  Widget build(BuildContext context) {
    final Size size = MediaQuery.of(context).size;
    controller.text = textForm ?? '';

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        isHelpPage
        ? const SizedBox()
        : const ResizedText(
          'Comments',
          textStyle: constants.Styles.smallTextStyleWhite,
        ),
        SizedBox(
          height: UiSize.getHeight(15, size),
        ),
        Container(
          height: UiSize.getHeight(isHelpPage ? 290 : 150, size),
          width: UiSize.getWidth(360, size),
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(8),
            border: Border.all(
              color: constants.Colors.purpleMain,
              width: 0.5,
            ),
          ),
          child: Padding(
            padding: EdgeInsets.only(
              top: UiSize.getHeight(16, size),
              left: UiSize.getWidth(18, size),
              right: UiSize.getWidth(18, size),
              bottom: UiSize.getHeight(16, size),
            ),
            child: TextField(
              maxLines: isHelpPage ? 10 :4,
              maxLength: isHelpPage ? 1500 : 450,
              controller: controller,
              style: constants.Styles.smallerBookTextStyleWhiteOpacity,
              textInputAction: TextInputAction.done,
              onChanged: (text) {
                onChanged(text);
                value = text;
              },
              decoration: InputDecoration(
                border: InputBorder.none,
                helperStyle: constants.Styles.smallerBookTextStyleWhiteOpacity,
                hintStyle: constants.Styles.smallerBookTextStyleWhiteOpacity,
                hintText: 'Here you can describe the problem in more detail',
              ),
            ),
          ),
        ),
      ],
    );
  }
}

body

class ReportBody extends StatelessWidget {
  final bool isHelpPage;
  ReportBody({Key? key, required this.isHelpPage}) : super(key: key);

  final TextEditingController controller = TextEditingController();

  @override
  Widget build(BuildContext context) {
    String? comment;
    final Size size = MediaQuery.of(context).size;

    return Container(
      height: size.height,
      width: size.width,
      decoration: const BoxDecoration(
        image: DecorationImage(
          image: AssetImage('assets/images/background/main_background.png'),
          fit: BoxFit.cover,
        ),
      ),
      child: _child(size, comment),
    );
  }

  Widget _child(Size size, String? comment) =>
      BlocBuilder<ReportCubit, ReportState>(
        builder: (context, state) {
          final ReportCubit cubit = BlocProvider.of<ReportCubit>(context);
          if (state is ReportInitial) {
            return _part(cubit, context, size, state, comment);
          }

          return Container();
        },
      );

  Widget _part(
    ReportCubit cubit,
    BuildContext context,
    Size size,
    ReportInitial state,
    String? comment,
  ) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        const SizedBox(
          height: 135,
        ),
        Padding(
          padding: const EdgeInsets.only(left: 30, right: 30),
          child: BackstepWidget(
            text: 'Report a problem',
            onBackPressed: () => Routemaster.of(context).pop(),
          ),
        ),
        state.isPhotoEnabled && state.reports[0]
            ? Expanded(
                child: SingleChildScrollView(
                  physics: const BouncingScrollPhysics(),
                  child: _reportBody(cubit, context, size, state, comment),
                ),
              )
            : Expanded(child: _reportBody(cubit, context, size, state, comment))
      ],
    );
  }

  Widget _reportBody(
    ReportCubit cubit,
    BuildContext context,
    Size size,
    ReportInitial state,
    String? comment,
  ) {
    return isHelpPage
    ? SingleChildScrollView(
      physics: const BouncingScrollPhysics(),
      child: ConstrainedBox(
        constraints: BoxConstraints(
          maxHeight: isHelpPage && state.isPhotoEnabled
              ? size.height * 0.98
              : size.height * .77,
        ),
        child: _reportWidget(cubit, context, size, state, comment),
      ),
    )
    : _reportWidget(cubit, context, size, state, comment);
  }

  Widget _reportWidget(
    ReportCubit cubit,
    BuildContext context,
    Size size,
    ReportInitial state,
    String? comment,
  ) {
    return Column(
      children: [
        if (state.reports[0] || isHelpPage)
          Padding(
            padding: EdgeInsets.only(
              top: isHelpPage ? 0 : UiSize.getHeight(48, size),
              bottom: UiSize.getHeight(30, size),
              right: UiSize.getWidth(28, size),
              left: UiSize.getWidth(28, size),
            ),
            child: CommentWidget(
              textForm: comment,
              onChanged: (text) {
                state.comment = text;
                comment = text;
                print(comment);
              },
              isHelpPage: isHelpPage,
            ),
          ),

CodePudding user response:

My guess is that you are rebuilding the textfield in the parent widget by maybe calling setState(...).

controller.text = textForm ?? ''; then wipes your text because you are resetting the text every time you are building the widget.

Solution: Make the widget a StatefulWidget and let it cache the value of the TextField.

This could look something like this

class TextfieldWithCache extends StatefulWidget {
  const TextfieldWithCache(this.initialValue, this.onUpdate);
  
  final String initialValue;
  final Function(String) onUpdate;

  @override
  State<TextfieldWithCache> createState() => TextfieldWithCacheState();
}

class TextfieldWithCacheState extends State<TextfieldWithCache> {
  
  // if not used in this widget, the value can be deleted as well
  String _cachedValue;
  
  Widget build(BuildContext context) {
    return TextFormField(
      initialValue: widget.initialValue,
      onChanged: (String value) {
        widget.onUpdate(value);
        _cachedValue = value;
      },
    );
  }
}

Note: If you don't use the cached value in the TextfieldWithCache then you can remove it as well.

The core lies in using a StatefulWidget and getting rid of all helper methods involved in widget creation.

CodePudding user response:

Try changing the ReportBody to Statefull Widget and declare the text editing controller as and intialize it in the initState(),

late final TextEditingController controller;

@override
  void initState() {
    controller = TextEditingController();
    super.initState();
  }

Then pass this controller to CommentWidget as a named paramater and use this contoller to TextFormField.

Hope it works.

  • Related