Reputation: 1013
Im using Flutter and flutter_bloc for a small app, and i used MultiBlocProvider to use multiple BlocProviders that i need in the main home page, and under the home page, there is a MainWidget, which can access the given Bloc easily by: BlocProvider.of<OldBloc>(context)
The MainWidget calls NewWidget as a dialog by: showDialog(context: context, builder: (context) => NewWidget())
The problem is, i cannot access OldBloc from NewWidget(), so i assumed that MainWidget isnt passing its context to NewWidget when using showDialog ?
HomeScreen.dart
import 'package:flutter/material.dart';
class HomeScreen extends StatelessWidget {
const HomeScreen({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: MultiBlocProvider(
providers: [
BlocProvider(
create: (context) => OldBloc()..add(Initialize()),
),
BlocProvider(
create: (context) => OtherBloc()..add(Initialize()),
),
],
child: Stack(
children: [
MainWidget(),
MenuWidget(),
],
),
));
}
}
MainWidget.dart
import 'package:flutter/material.dart';
class MainWidget extends StatelessWidget {
const MainWidget({
Key key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return TextField(onTap: () => showDialog(context: context, builder: (context) => NewWidget()));
}
}
NewWidget.dart
import 'package:flutter/material.dart';
class NewWidget extends StatelessWidget {
const NewWidget({Key key}) : super(key: key);
@override
Widget build(context) {
return Text(BlocProvider.of<OldBloc>(context).name); // <------- THIS GIVES AN ERROR THAT IT CANT FIND A BLOC OF THE TYPE OldBloc
}
}
Upvotes: 12
Views: 5942
Reputation: 550
You can simply use this (suggested by Flex Angelov):
class SimpleWidget extends StatelessWidget {
const SimpleWidget({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (_) => FilesBloc(),
child: Builder(
builder: (builderContext) => TextButton(
onPressed: () => _onTapSubmit(builderContext),
child: Text('Submit'),
),
),
);
}
void _onTapSubmit(BuildContext builderContext) {
showDialog(
context: builderContext,
builder: (_) {
return BlocProvider.value(
value: builderContext.read<FilesBloc>(),
child: const MyDialogWidget(),
);
},
);
}
}`
You can replace Builder with a BlocBuilder.
Upvotes: 14
Reputation: 89
I solved this problem.
I use cubit instead of bloc but it doesn't matter.
ShowDialog doesn't pass parent context. So you should create a new cubit and pass your parent cubit and state in arguments for a new cubit. I called main cubit FooCubit, new cubit FooCubitWrapper and DialogWidget is child widget that needs some BLOC logic in showDialog.
var fooCubit = context.read<FooCubit>(); // your parrent cubit and state
return BlocBuilder<FooCubit , FooState>(
builder: (_, state) {
.
.///some logic///
.
showDialog(
context: context,
builder: (_) => // here you have to create new cubit
BlocProvider( // because there is no access to parent cubit
create: (_) => FooCubitWrapper(cubit, state),
child: DialogWidget(),
),
);
This is FooCubitWrapper. For example, we need the boo method from the parent cubit. So we need to create here boo method and inside we need to reference to parent boo method and emit parent state.
class FooCubitWrapper extends Cubit<FooState> {
FooCubit fooCubit;
FooCubitWrapper(this.fooCubit, FooState initialState) : super(initialState);
boo() {
fooCubit.boo();
emit(fooCubit.state);
}
}
And finally, in your DialogWidget, you do all like usual
var cubit = context.read<TagsCubitWrapper>();
return BlocBuilder<TagsCubitWrapper, TagsState>(
builder: (context, state) {
// work with methods and fields as usual
cubit.boo();
if !(state.someField) {}
});
Upvotes: 0
Reputation: 3136
You have no access to BuildContext
in your showDialog
method, documentation:
The widget returned by the builder does not share a context with the location that showDialog is originally called from.
The context argument is used to look up the Navigator and Theme for the dialog. It is only used when the method is called.
Its also recommended to use a StatefulBuilder
or a custom StatefulWidget
, here is an example.
Upvotes: 4