Home > other >  Cannot use TextField properly with RiverPod in Flutter
Cannot use TextField properly with RiverPod in Flutter

Time:10-17

I am new on RiverPod. I want to get input from user bıt I couldn't use a TextField in my app with RiverPod.TextController's value is empty.

Also I got an error FormatError:Invalid Number

final User_value = StateProvider<int>((ref) {
  return 0;
});

final controller = TextEditingController();
final controllerprovider = StateProvider<String>((ref) {
  return controller.text;
});

class HomePage extends ConsumerWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final controllertext = ref.watch(controllerprovider);
    final user_value = ref.watch(User_value);

    return Scaffold(
        appBar: AppBar(
          title: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text("Home"),
            ],
          ),
        ),
        body: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              child: Text("Go to the Counter page"),
              onPressed: () {
                Navigator.of(context).push(
                  //Navigation
                  MaterialPageRoute(builder: (((context) => CounterPage()))),
                );
              },
            ),
            SizedBox(
              height: 60,
            ),
            TextField(
              controller: controller,
              decoration: InputDecoration(
                  labelText: "Enter a number", 
                  border: OutlineInputBorder(), 
                  prefixIcon: Icon(Icons.numbers),
                  suffixIcon: controllertext.isEmpty
                      ? Container(
                          width: 0,
                        )
                      : IconButton(
                          icon: Icon(Icons.close), //If user wants to enter another number this is the easy way to delete the current one.
                          onPressed: () {
                            ref.invalidate(controllerprovider);
                            
                          },
                        )),
            ),
            
            IconButton(
                onPressed: () {
                  temp = ref.read(User_value.notifier).state;
                  print(controllertext);
                  ref.read(User_value.notifier).state =
int.parse(ref.read(controllerprovider.notifier).state); // Thats where I got the error.

                  ScaffoldMessenger.of(context).showSnackBar(SnackBar(
                    content: Text("Input has been saved"),
                    action: SnackBarAction(
                      label: "Undo",
                      onPressed: () {
                        ref.read(User_value.notifier).state = temp;
                      },
                    ),
                  ));
                },
                icon: Icon(Icons.add_task)),
       ],
        ));
  }
}

I couldn't solve how to get input from user.User should be enter a number,click the button and the number should be saved as controller's state.

CodePudding user response:

It is better to use int.tryParse and provide a default value on exceptions, you dont need to use global TextEditingController. You can follow this widget.

final userValueProvider = StateProvider<int>((ref) {
  return 0;
});

final controllerProvider = StateProvider<String>((ref) {
  return "";
});

class HomePage extends ConsumerWidget {
  HomePage({Key? key}) : super(key: key);
  final controller = TextEditingController();
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final controllerText = ref.watch(controllerProvider);
    final userValue = ref.watch(userValueProvider);
    debugPrint("rebuilding");
    return Scaffold(
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text("controllerText $controllerText userValue $userValue"),
          TextField(
            controller: controller,
            onChanged: (value) {
              debugPrint(value);
              ref.read(controllerProvider.notifier).state = value;
            },
            decoration: InputDecoration(
                labelText: "Enter a number",
                suffixIcon: controllerText.isEmpty
                    ? null
                    : IconButton(
                        icon: const Icon(Icons.close),
                        onPressed: () {
                          ref.read(controllerProvider.notifier).state = ""; //prefer using .update
                          controller.clear(); //clear TextField
                        },
                      )),
          ),
          IconButton(
              onPressed: () {
                final oldValue = ref.read(userValueProvider.notifier).state;
                ref
                    .read(userValueProvider.notifier)
                    .update((state) => int.tryParse(controller.text) ?? 0);

                ScaffoldMessenger.of(context).showSnackBar(SnackBar(
                  content: const Text("Input has been saved"),
                  action: SnackBarAction(
                    label: "Undo",
                    onPressed: () {
                      ref
                          .read(userValueProvider.notifier)
                          .update((state) => oldValue);
                    },
                  ),
                ));
              },
              icon: const Icon(Icons.add_task)),
        ],
      ),
    );
  }
}
  • Related