Skip to content

Instantly share code, notes, and snippets.

@IsmailAlamKhan
Created November 12, 2021 15:37
Show Gist options
  • Save IsmailAlamKhan/4c5db32fab419037f6035cb15eded007 to your computer and use it in GitHub Desktop.
Save IsmailAlamKhan/4c5db32fab419037f6035cb15eded007 to your computer and use it in GitHub Desktop.
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