Kvu
Kvu

Reputation: 309

Flutter Exception - Invalid number (at character 1) TextFormField

I'm trying to display a scaffold msg when user inputted a value greater than some other value...

It is working fine until I clear the input...

After clearing the input it throws an exception...

Here it is...

══╡ EXCEPTION CAUGHT BY WIDGETS ╞═══════════════════════════════════════════════════════════════════
The following FormatException was thrown while calling onChanged:
Invalid number (at character 1)

^

When the exception was thrown, this was the stack:
#0      int._handleFormatError (dart:core-patch/integers_patch.dart:129:7)
#1      int.parse (dart:core-patch/integers_patch.dart:55:14)
#2      _GeneralTabState.build.<anonymous closure>.<anonymous closure>
(package:shop_app_vendor/screens/add_products/general_tab.dart:247:25)
#3      new TextFormField.<anonymous closure>.onChangedHandler (package:flutter/src/material/text_form_field.dart:188:25)
#4      EditableTextState._formatAndSetValue (package:flutter/src/widgets/editable_text.dart:2630:27)
#5      EditableTextState.userUpdateTextEditingValue (package:flutter/src/widgets/editable_text.dart:2919:5)
#6      EditableTextState._replaceText (package:flutter/src/widgets/editable_text.dart:3144:5)
#7      CallbackAction.invoke (package:flutter/src/widgets/actions.dart:534:39)
#8      ActionDispatcher.invokeAction (package:flutter/src/widgets/actions.dart:573:21)
#9      Actions.invoke.<anonymous closure> (package:flutter/src/widgets/actions.dart:872:48)
#10     Actions._visitActionsAncestors (package:flutter/src/widgets/actions.dart:653:18)
#11     Actions.invoke (package:flutter/src/widgets/actions.dart:866:30)
#12     _DeleteTextAction.invoke (package:flutter/src/widgets/editable_text.dart:4042:20)
#13     _OverridableContextAction.invokeDefaultAction (package:flutter/src/widgets/actions.dart:1696:28)
#14     _OverridableActionMixin.invoke (package:flutter/src/widgets/actions.dart:1559:9)
#15     ActionDispatcher.invokeAction (package:flutter/src/widgets/actions.dart:571:21)
#16     ShortcutManager.handleKeypress (package:flutter/src/widgets/shortcuts.dart:755:38)
#17     _ShortcutsState._handleOnKey (package:flutter/src/widgets/shortcuts.dart:956:20)
#18     FocusManager._handleKeyMessage (package:flutter/src/widgets/focus_manager.dart:1687:32)
#19     KeyEventManager._dispatchKeyMessage (package:flutter/src/services/hardware_keyboard.dart:828:34)
#20     KeyEventManager.handleRawKeyMessage (package:flutter/src/services/hardware_keyboard.dart:875:15)
#21     BasicMessageChannel.setMessageHandler.<anonymous closure> (package:flutter/src/services/platform_channel.dart:77:49)      
#22     BasicMessageChannel.setMessageHandler.<anonymous closure> (package:flutter/src/services/platform_channel.dart:76:47)      
#23     _DefaultBinaryMessenger.setMessageHandler.<anonymous closure> (package:flutter/src/services/binding.dart:380:35)
#24     _DefaultBinaryMessenger.setMessageHandler.<anonymous closure> (package:flutter/src/services/binding.dart:377:46)
#25     _invoke2.<anonymous closure> (dart:ui/hooks.dart:190:15)
#29     _invoke2 (dart:ui/hooks.dart:189:10)
#30     _ChannelCallbackRecord.invoke (dart:ui/channel_buffers.dart:42:5)
#31     _Channel.push (dart:ui/channel_buffers.dart:132:31)
#32     ChannelBuffers.push (dart:ui/channel_buffers.dart:329:17)
#33     PlatformDispatcher._dispatchPlatformMessage (dart:ui/platform_dispatcher.dart:589:22)
#34     _dispatchPlatformMessage (dart:ui/hooks.dart:89:31)
(elided 3 frames from dart:async)
════════════════════════════════════════════════════════════════════════════════════════════════════

And here's my code...

scf.dart

class SCF {
  scaffoldMsg({context, msg}) {
    ScaffoldMessenger.of(context).showSnackBar(SnackBar(
      content: Text(msg),
      backgroundColor: Colors.red,
      action: SnackBarAction(
        label: 'OK',
        textColor: Colors.white,
        onPressed: () {
          ScaffoldMessenger.of(context).clearSnackBars();
        },
      ),
    ));
  }
}

general_tab.dart

class GeneralTab extends StatefulWidget {
  const GeneralTab({Key? key}) : super(key: key);

  @override
  State<GeneralTab> createState() => _GeneralTabState();
}

class _GeneralTabState extends State<GeneralTab> {
  final SCF _scf = SCF();

  @override
  Widget build(BuildContext context) {
    return Consumer<ProductProvider>(
      builder: (context, provider, child) {
        return ListView(
          padding: const EdgeInsets.all(15.0),
          children: [
            // Regular Price
            FormFieldInput(
              label: 'Regular Price',
              inputType: TextInputType.number,
              onChanged: (value) {
                provider.getFormData(regularPrice: int.parse(value));
              },
            ),
            // Sales Price
            FormFieldInput(
              label: 'Sales Price',
              inputType: TextInputType.number,
              onChanged: (value) {
                if (int.parse(value) > provider.productData!['regularPrice']) {
                  _scf.scaffoldMsg(
                    context: context,
                    msg: 'Sales price should be less than regular price',
                  );
                }
                setState(() {
                  provider.getFormData(salesPrice: int.parse(value));
                });
              },
            ),
          ],
        );
      },
    );
  }
}

product_provider.dart

class ProductProvider with ChangeNotifier {
  Map<String, dynamic>? productData = {};

  getFormData({
    int? regularPrice,
    int? salesPrice,
  }) {
    if (regularPrice != null) {
      productData!['regularPrice'] = regularPrice;
    }

    if (salesPrice != null) {
      productData!['salesPrice'] = salesPrice;
    }

    notifyListeners();
  }
}

form_field.dart

class FormFieldInput extends StatelessWidget {
  final String? label;
  final void Function(String)? onChanged;
  final TextInputType? inputType;

  const FormFieldInput({
    Key? key,
    this.label,
    this.onChanged,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return TextFormField(
      decoration: InputDecoration(
        label: Text(label!),
      ),
      onChanged: onChanged,
    );
  }
}

This is working fine and showing scaffold msg until I delete the content in the input...

So how can I fix this?

Upvotes: 0

Views: 1361

Answers (2)

Kvu
Kvu

Reputation: 309

I found a solution.

By adding if(value.isNotEmpty) to the on change error is gone...

Need to check whether value is empty or not.

That's how I solved my problem.

Thank you

general_tab.dart

class GeneralTab extends StatefulWidget {
  const GeneralTab({Key? key}) : super(key: key);

  @override
  State<GeneralTab> createState() => _GeneralTabState();
}

class _GeneralTabState extends State<GeneralTab> {
  final SCF _scf = SCF();

  @override
  Widget build(BuildContext context) {
    return Consumer<ProductProvider>(
      builder: (context, provider, child) {
        return ListView(
          padding: const EdgeInsets.all(15.0),
          children: [
            // Regular Price
            FormFieldInput(
              label: 'Regular Price',
              inputType: TextInputType.number,
              onChanged: (value) {
                if (value.isNotEmpty) {
                  provider.getFormData(regularPrice: int.parse(value));
                }
              },
            ),
            // Sales Price
            FormFieldInput(
              label: 'Sales Price',
              inputType: TextInputType.number,
              onChanged: (value) {
                if (value.isNotEmpty) {
                  if (int.parse(value) > provider.productData!['regularPrice']) {
                    _scf.scaffoldMsg(
                      context: context,
                      msg: 'Sales price should be less than regular price',
                    );
                  }
                }
                setState(() {
                  provider.getFormData(salesPrice: int.parse(value));
                });
              },
            ),
          ],
        );
      },
    );
  }
}

Upvotes: 0

Ahmad Ellamey
Ahmad Ellamey

Reputation: 331

that's because when the the text is empty the app cast the empty to number so this error happened when you reach the compare , so you need to check if the text is not empty before you trigger the compare.

  • so in your case in the onChange function before trigger any logic ,make sure that the value in the text field is not null or empty.

Upvotes: 1

Related Questions