Quantcast
Viewing all articles
Browse latest Browse all 91

What is the correct way to update two related fields using Riverpod in Flutter?

I am trying to implement two related fields in a form using Riverpod in Flutter. The first field is a segmented class type selection, and the second is a text field for entering a custom class type. I need that when selecting a value from a segmented list, the input field is cleared, and vice versa — if a value is entered in the input field, it should reset the selection from the segmented list.

If I enter a value in a custom field, the selection is removed from the button. But by selecting the button, the custom field is not cleared, although it is strange.

import 'package:flutter/material.dart';import 'package:flutter_riverpod/flutter_riverpod.dart';void main() {  runApp(    const ProviderScope(child: MyApp()),  );}class MyApp extends StatelessWidget {  const MyApp({super.key});  @override  Widget build(BuildContext context) {    return MaterialApp(      home: Scaffold(        appBar: AppBar(title: const Text('Segmented Button and TextFormField')),        body: Padding(          padding: const EdgeInsets.all(16.0),          child: Column(            children: [              //               SizedBox(                width: double.infinity,                child: Consumer(                  builder: (context, ref, child) {                    final lessonState = ref.watch(lessonControllerProvider);                    return SegmentedButton<String>(                      showSelectedIcon: false,                      emptySelectionAllowed: true,                      style: SegmentedButton.styleFrom(                        shape: const RoundedRectangleBorder(                          borderRadius: BorderRadius.all(Radius.circular(4)),                        ),                      ),                      segments: [                        LessonSegment(value: '1', text: '1'),                        LessonSegment(value: '2', text: '2'),                        LessonSegment(value: '3', text: '3'),                      ],                      selected: {lessonState.lessonType},                      onSelectionChanged: (Set<String> value) {                        if (value.isNotEmpty) {                          final selectedValue = value.first;                          ref                              .read(lessonControllerProvider.notifier)                              .updateField('lessonType', selectedValue);                        }                      },                    );                  },                ),              ),              const SizedBox(height: 8),              //               Consumer(                builder: (context, ref, child) {                  final lessonState = ref.watch(lessonControllerProvider);                  return TextFormField(                    textAlign: TextAlign.center,                    initialValue: lessonState.customLessonType,                    decoration: InputDecoration(                      border: const OutlineInputBorder(),                      hintText: 'custom',                      hintStyle: Theme.of(context).textTheme.labelLarge,                      errorMaxLines: 2,                    ),                    onChanged: (value) {                      ref                          .read(lessonControllerProvider.notifier)                          .updateField('customLessonType', value);                    },                    validator: (value) {                      if ((lessonState.lessonType.isEmpty &&                              (value == null || value.isEmpty)) ||                          (lessonState.lessonType.isNotEmpty &&                              value?.isNotEmpty == true)) {                        return 'error';                      }                      return null;                    },                  );                },              ),            ],          ),        ),      ),    );  }}class LessonState {  final String lessonType;  final String customLessonType;  LessonState({    this.lessonType = '',    this.customLessonType = '',  });  LessonState copyWith({    String? lessonType,    String? customLessonType,  }) {    return LessonState(      lessonType: lessonType ?? this.lessonType,      customLessonType: customLessonType ?? this.customLessonType,    );  }}class LessonController extends StateNotifier<LessonState> {  LessonController() : super(LessonState());  void updateField(String field, String value) {    switch (field) {      case 'lessonType':        state = state.copyWith(lessonType: value, customLessonType: '');        break;      case 'customLessonType':        state = state.copyWith(customLessonType: value, lessonType: '');        break;    }  }}final lessonControllerProvider =    StateNotifierProvider<LessonController, LessonState>(  (ref) => LessonController(),);class LessonSegment extends ButtonSegment<String> {  LessonSegment({required super.value, required String text})      : super(          label: Padding(            padding: const EdgeInsets.symmetric(vertical: 14.0),            child: Text(text),          ),        );}

Viewing all articles
Browse latest Browse all 91

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>