Im creating a flutter app with bloc, and I'm not able to use the block provider.
My main.dart:
class _MyHomePageState extends State<MyHomePage> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider(create: (_) => ManageBloc()),
BlocProvider(create: (_) => MonitorBloc()),
],
child: Builder(
builder: (context) => Scaffold(
appBar: AppBar(
title: Row(children: [
const Icon(Icons.wallet),
Text(widget.title),
]),
bottom: const TabBar(tabs: [
Tab(icon: Icon(Icons.home)),
Tab(icon: Icon(Icons.compare_arrows)),
Tab(icon: Icon(Icons.monetization_on))
]),
),
body: const TabBarView(
children: [
HomeScreen(),
OperationsView(),
PricesScreen(),
]),
floatingActionButton: FloatingActionButton(
onPressed: () {
showModalBottomSheet(context: context, builder: (BuildContext context) {
return NewOperation();
});
},
hoverColor: Colors.white,
backgroundColor: Colors.white10,
child: const Icon(Icons.add, color: Colors.lightBlue,),
),
),
));
}
}
When i click the floating button and try to view the NewOperation component, i recive the error. NewOperation:
class NewOperation extends StatelessWidget {
final GlobalKey<FormState> _formKey = GlobalKey();
final Operation operation = Operation();
bool _isEntry = false;
@override
Widget build(BuildContext context) {
return BlocBuilder<ManageBloc, ManageState>(builder: (context, state) {
Operation operation;
if (state is UpdateState) {
operation = state.previousOperation;
} else {
operation = Operation();
}
return Form(
key: _formKey,
child: Column(
children: [
TextFormField(
keyboardType: const TextInputType.numberWithOptions(
decimal: true),
validator: (String? inValue) {
if (inValue != null) {
if (double.parse(inValue) <= 0.0) {
return "Valor inválido!";
}
}
return null;
},
decoration: const InputDecoration(
hintText: "00.0",
labelText: "Valor da Operação",
),
),
TextFormField(
keyboardType: TextInputType.multiline,
validator: (String? inValue) {
if (inValue != null) {
if (inValue.length < 3) {
return "Addiction uma descrição mais detalhada!";
}
}
return null;
},
decoration: const InputDecoration(
hintText: "Conta de luz",
labelText: "Descrição",
),
),
Row(children: [
const Text("Entrada"),
Switch(value: _isEntry, onChanged: (bool inValue) {
// handleIsEntry(inValue);
}),
const Text("Saída"),
]),
ElevatedButton(onPressed: () {
if (_formKey.currentState!.validate()) {
_formKey.currentState!.save();
BlocProvider.of<ManageBloc>(context).add(SubmitEvent(operation: operation));
_formKey.currentState!.reset();
}
}, child: const Text("Salvar"))
],
));
});
}
}
What's the mistake?
I tried to put the floating button inside the MultiBlocProvider, and dosnt work.
CodePudding user response:
You need to provide the bloc to the modal as you do with e.g. dialogs.
Try providing the bloc to the modal. You can do something like this:
showModalBottomSheet(
context: context,
builder: (modalContext) => BlocProvider.value(
value: BlocProvider.of<ManageBloc>(context),
child: NewOperation(),
),
CodePudding user response:
You are providing the BLoC only in the context of "MyHomePage". The Blocs you are trying to provide will go down the widget tree of MyHomePage.
When you are displaying the modal bottom sheet, you are actually creating a new context for it, which is not below the MyHomePage widget tree, so the Blocs won't reach the bottom sheet.
You have 2 options:
- Provide the Bloc manually again to the bottom sheet. Refer to Robert Sandberg answer
- Provide the Bloc to the whole app. This means wrapping your MaterialApp with a MultiBlocProvider. This will make your Bloc usable everywhere.
return MultiBlocProvider(
providers: [
BlocProvider(create: (_) => ManageBloc()),
...
],
child: MaterialApp(...),
)
For more information on BuildContext and Providers please refer to this video: https://www.youtube.com/watch?v=iNgwFMm3opE&t=2s