Reputation: 443
Im having two screens.
lets say Screen1 and Screen2.
Screen 1 is within a TabView and have couple of checkboxes which I need to validate if either is chosen before proceeding to get them from there and pass to an API call from a button which is in Screen2. Screen2 is the parent(holder) of the TabViews.
Basically ,
I can manage the API calling part. but wanna have an idea or an example of managing the above between Screen1 and Screen2. Can someone provide and insight or an example?
Update
with a helpful comment from a fellow flutter enthusiast, I've update the code. The widget flow is as follows.
//ParentWidget ==> has the list if TabViews and also a button to submit,
TabBarView(
controller: _tabController,
physics: NeverScrollableScrollPhysics(),
children: _tabViewList,
)
//and the button
Consumer<UpdateItemProvider>(
builder: (_, UpdateItemProvider updateItemProvider, __) {
return ButtonWidget(
btnColor: CustomColors.green600,
borderColor: CustomColors.green600,
textColor: CustomColors.mWhite,
text: "Continue",
eButtonType: eButtonType.bText,
eButtonState: _continueBtnState,
onPressed: () {
if (updateItemProvider.updateItems!.isEmpty) {
setState(() {
_continueBtnState = eButtonState.bDisable;
});
} else {
setState(() {
_continueBtnState = eButtonState.bActive;
});
forwardTabPage(updateItemProvider.updateItems!);
}
// _tabState = eTabState.tCompleted;
},
);
},
// child:
);
----------
//A TabView widget(child) is a Stateful widget
@override
Widget build(BuildContext context) {
final UpdateItemProvider _updateItemProvider =
Provider.of<UpdateItemProvider>(context, listen: false);
//inside the child widget I have a list view which loads checkbox list tiles
and im using the provider there
ListView(
shrinkWrap: true,
children: _rampValues.keys.map((String key) {
return CheckboxListTile(
title: Text(key, style: tBody5),
value: _rampValues[key],
onChanged: (value) {
setState(() {
_rampValues[key] = value!;
});
if (_rampValues[key] == true) {
_updateItemProvider.addItem(new UpdateItem(
title: key, selected: _rampValues[key]));
} else {
_updateItemProvider.removeWhere(key);
}
},
);
}).toList(),
),
}
When I execute with above updates. I get this error
Error: Could not find the correct Provider<UpdateItemProvider> above this {child_here} Widget
This happens because you used a `BuildContext` that does not include the provider
of your choice. There are a few common scenarios:
Upvotes: 0
Views: 1396
Reputation: 4750
Your Code is Fine , the Missing Part is You need to register the provider in main.dart file .
Example : **Provider<UpdateItemProvider>**
this Provider is missing. So
void main() async {
WidgetsFlutterBinding.ensureInitialized();
SystemChrome.setPreferredOrientations(
[DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]).then((_) {
runApp(MyApp());
});
}
/*
this is main page of this project we will use the provider system to maintian the application states
*/
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MultiProvider(
/**
* Providers For the Block Module of the System
*/
providers: [
ChangeNotifierProvider(create: (ctx) => LoginProvider()), // Add your Provider Here
],
child: Consumer<LoginProvider>(
builder: (ctx, auth, _) => MaterialApp(
title: 'Baghaa',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.orange,
accentColor: Colors.black,
fontFamily: 'RobotoCondensed',
textTheme: ThemeData.light().textTheme.copyWith(
bodyText1: TextStyle(
color: Color.fromRGBO(20, 51, 51, 1),
),
bodyText2: TextStyle(
color: Color.fromRGBO(20, 51, 51, 1),
),
headline1: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
fontFamily: 'RobotoCondensed',
)),
canvasColor: Color.fromRGBO(255, 254, 229, 1),
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: .... Your Home widget
),
);
}
}
Upvotes: 2
Reputation: 1619
You may use any kind of reactive way to access the data globally using Provider, GetX, Bloc and etc.
You may use GetX observables like below:
Reactive programming with Get is as easy as using setState.
Let's imagine that you have a name variable and want that every time you change it, all widgets that use it are automatically changed.
This is your count variable:
var name = 'Jonatas Borges';
To make it observable, you just need to add ".obs"
to the end of it:
var name = 'Jonatas Borges'.obs;
And in the UI, when you want to show that value and update the screen whenever the values changes, simply do this:
Obx(() => Text("${controller.name}"));
That's all. It's that simple.
You will find the plugin here
Upvotes: 1
Reputation: 8274
Without any code to go by, We can use a shopping cart as an example.
Ideally you need a way to manage your list of items and checkout in the next page.
We will use provider for this.
class MyCartProvider extends ChangeNotifier{
List<CartItem>? cartItems=[];
List<CartItem>? get getCartItems=>cartItems;
removeATIndex(int i){
cartItems.removeAt(i);
notifyListeners();
}
inserAtIndex(int i,CartItem? item){
cartItems![i]=item;
notifyListeners();
}
addItem(CartItem? item){
cartItems.add(item);
notifyListeners()
}
}
Once we have our provider now we can insert/add data as we wish and use a consumer in the second screen to get our data.
how to add data ...
class MyItemsScreen extends StatefulWidget {
const MyItemsScreen({ Key? key }) : super(key: key);
@override
_MyItemsScreenState createState() => _MyItemsScreenState();
}
class _MyItemsScreenState extends State<MyItemsScreen> {
@override
Widget build(BuildContext context) {
final cartItemsProvider = Provider.of<MyCartProvider>(context,
listen: false);
return Scaffold(
appBar: AppBar(),
body: Column(children: [
//my cart items
mycartitem(onTap:(
cartItemsProvider.addItem(mycartItem);
))
],),
);
}
}
In screen B
Container(
child: Consumer<MyCartProvider>(
builder: (context,MyCartProvider cartProvider, child) {
//you can even return a list view of all the items here
return ElevatedButton(
onPressed:(){ //your api calls
cartProvider.cartItems // the data you need is here
},
),
),
Upvotes: 3