Created
November 12, 2021 15:37
-
-
Save IsmailAlamKhan/4c5db32fab419037f6035cb15eded007 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
import 'package:flutter_riverpod/flutter_riverpod.dart'; | |
final myNotifierProvider = StateNotifierProvider<MyNotifier, MyState>((_) => MyNotifier()); | |
void main() => runApp(const ProviderScope(child: MyApp())); | |
class MyApp extends StatelessWidget { | |
const MyApp({Key? key}) : super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
return const MaterialApp(title: 'Material App', home: Home()); | |
} | |
} | |
class Home extends ConsumerWidget { | |
const Home({ | |
Key? key, | |
}) : super(key: key); | |
@override | |
Widget build(BuildContext context, WidgetRef ref) { | |
final state = ref.watch(myNotifierProvider); | |
final notifier = ref.watch(myNotifierProvider.notifier); | |
return Scaffold( | |
appBar: AppBar(title: const Text('Material App Bar')), | |
body: Center( | |
child: Column( | |
children: [ | |
MyTextfield(state: state.password, onChanged: notifier.passwordChanged), | |
const SizedBox(height: 16), | |
MyTextfield(state: state.username, onChanged: notifier.usernameChanged), | |
const SizedBox(height: 16), | |
ElevatedButton( | |
onPressed: notifier.submit(), | |
child: const Text('Submit'), | |
), | |
], | |
), | |
), | |
); | |
} | |
} | |
class MyTextfieldState { | |
final String value; | |
final String label; | |
final String? errorText; | |
const MyTextfieldState({ | |
required this.label, | |
this.value = '', | |
this.errorText, | |
}); | |
MyTextfieldState copyWith({ | |
String? value, | |
String? label, | |
String? errorText, | |
}) { | |
return MyTextfieldState( | |
value: value ?? this.value, | |
label: label ?? this.label, | |
errorText: errorText, | |
); | |
} | |
} | |
class MyState { | |
final MyTextfieldState password; | |
final MyTextfieldState username; | |
const MyState({ | |
this.password = const MyTextfieldState(label: 'password'), | |
this.username = const MyTextfieldState(label: 'username'), | |
}); | |
MyState copyWith({ | |
MyTextfieldState? password, | |
MyTextfieldState? username, | |
bool? canSubmit, | |
}) { | |
return MyState( | |
password: password ?? this.password, | |
username: username ?? this.username, | |
); | |
} | |
bool get canSubmit => password.errorText == null && username.errorText == null; | |
} | |
class MyNotifier extends StateNotifier<MyState> { | |
MyNotifier() : super(const MyState()); | |
void usernameChanged(String username) { | |
state = state.copyWith( | |
username: state.username.copyWith( | |
errorText: username.isEmpty ? 'username is required' : null, | |
value: username, | |
), | |
); | |
} | |
void passwordChanged(String password) { | |
state = state.copyWith( | |
password: state.password.copyWith( | |
errorText: password.isEmpty ? 'password is required' : null, | |
value: password, | |
), | |
); | |
} | |
VoidCallback? submit() { | |
if (state.canSubmit) { | |
return () { | |
debugPrint('submit'); | |
}; | |
} | |
} | |
} | |
class MyTextfield extends StatefulWidget { | |
const MyTextfield({ | |
Key? key, | |
required this.state, | |
this.onChanged, | |
}) : super(key: key); | |
final MyTextfieldState state; | |
final ValueChanged<String>? onChanged; | |
@override | |
State<MyTextfield> createState() => _MyTextfieldState(); | |
} | |
class _MyTextfieldState extends State<MyTextfield> { | |
late final tec = TextEditingController(text: widget.state.value); | |
@override | |
void initState() { | |
super.initState(); | |
tec.addListener(() => widget.onChanged?.call(tec.text)); | |
} | |
@override | |
void dispose() { | |
tec.dispose(); | |
super.dispose(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Padding( | |
padding: const EdgeInsets.all(8.0), | |
child: TextField( | |
controller: tec, | |
decoration: InputDecoration( | |
labelText: widget.state.label, | |
errorText: widget.state.errorText, | |
), | |
), | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment