I'm trying to learn Bloc state management and developing a simple app to learn.
when the user types anything in a TextField
that text will be displayed under the field.
and now I'm sending the text field controller to the bloc file by declaring the controller globally.
final textController = TextEditingController();
but I want to know if there is any way to send the controller value to the bloc file from UI code (without global declaring)
Please refer to the below code
Solution 1
Bloc Class
import 'package:bloc/bloc.dart';
import 'package:meta/meta.dart';
part 'demo_event.dart';
part 'demo_state.dart';
class DemoBloc extends Bloc<DemoEvent, DemoState> {
DemoBloc() : super(DemoNoInputState());
@override
Stream<DemoState> mapEventToState(DemoEvent event) async* {
if (event is GetInput) {
yield* _mapGetInputEventToState(event);
}
}
Stream<DemoState> _mapGetInputEventToState(GetInput event) async* {
// showInputfromBloc() {
// // Call an API
// }
// showInputfromBloc();
yield DemoInitial(inputText: event.inputText);
}
}
Event Class
part of 'demo_bloc.dart';
@immutable
abstract class DemoEvent {}
class GetInput extends DemoEvent {
String inputText;
GetInput(this.inputText);
}
State
part of 'demo_bloc.dart';
@immutable
abstract class DemoState {}
class DemoInitial extends DemoState {
String? inputText;
DemoInitial({this.inputText});
}
class DemoNoInputState extends DemoState {}
class _MyHomePageState extends State<MyHomePage> {
final DemoBloc demoBloc = DemoBloc();
TextEditingController textEditingController = TextEditingController();
@override
void initState() {
super.initState();
}
@override
void dispose() {
demoBloc.close();
textEditingController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Padding(
padding: const EdgeInsets.all(15.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'Enter Input',
),
TextField(
controller: textEditingController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Input',
hintText: 'Enter Input',
),
),
BlocBuilder<DemoBloc, DemoState>(
bloc: demoBloc,
builder: (context, state) {
if (state is DemoInitial) {
return Text(
'${state.inputText}',
style: Theme.of(context).textTheme.headline4,
);
} else if (state is DemoNoInputState) {
return const SizedBox.shrink();
} else {
return const SizedBox.shrink();
}
},
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
demoBloc.add(GetInput(textEditingController.text));
},
child: const Center(child: Text("Result")),
),
);
}
}
Solution 2
class _MyHomePageState extends State<MyHomePage> {
final DemoBloc demoBloc = DemoBloc();
TextEditingController textEditingController = TextEditingController();
@override
void initState() {
super.initState();
}
@override
void dispose() {
demoBloc.close();
textEditingController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Padding(
padding: const EdgeInsets.all(15.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'Enter Input',
),
BlocBuilder<DemoBloc, DemoState>(
bloc: demoBloc,
builder: (context, state) {
if (state is DemoInitial) {
return Column(
children: [
TextField(
controller: textEditingController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Input',
hintText: 'Enter Input',
),
onChanged: (value) {
demoBloc.add(GetInput(textEditingController.text));
},
),
if (textEditingController.text.isNotEmpty)
Text(
'${state.inputText}',
style: Theme.of(context).textTheme.headline4,
),
],
);
} else {
return const SizedBox.shrink();
}
},
),
],
),
),
);
}
}
Bloc Class
import 'package:bloc/bloc.dart';
import 'package:meta/meta.dart';
part 'demo_event.dart';
part 'demo_state.dart';
class DemoBloc extends Bloc<DemoEvent, DemoState> {
DemoBloc() : super(DemoInitial());
@override
Stream<DemoState> mapEventToState(DemoEvent event) async* {
if (event is GetInput) {
yield* _mapGetInputEventToState(event);
}
}
Stream<DemoState> _mapGetInputEventToState(GetInput event) async* {
yield DemoInitial(inputText: event.inputText);
}
}
State
part of 'demo_bloc.dart';
@immutable
abstract class DemoState {}
class DemoInitial extends DemoState {
String? inputText;
DemoInitial({this.inputText});
}