Reputation: 373
I was trying to make a single screen with two view that change with index. I created _pages list inside initState like this.
class AddPlan extends StatefulWidget {
static const routeName = "addPlan";
@override
_AddPlanState createState() => _AddPlanState();
}
class _AddPlanState extends State<AddPlan> {
List<Object>? _pages;
int _selectedIndex = 0;
Map<dynamic, dynamic> _stepVals = {};
_setSelectedIndex(int newIndex, Map<dynamic, dynamic> newMap) {
setState(() {
_stepVals = {..._stepVals, ...newMap};
_selectedIndex = newIndex;
});
}
@override
void initState() {
// TODO: implement initState
_pages = [
StepOne(_setSelectedIndex),
StepTwo(_stepVals, _setSelectedIndex)
];
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.transparent,
),
body: Container(
margin: EdgeInsets.only(top: 10),
padding: EdgeInsets.symmetric(horizontal: 10),
child: _pages![_selectedIndex] as Widget,
),
);
}
}
And from StepOne() widget I call this to pass data and change index. widget.setNewIndex is my _setSelectedIndex fuction. The name is changed in my StepOne constructor.
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
_formKey.currentState!.save();
widget.setNewIndex(1, {
"title": title,
"age": age,
"description": description,
"dificulty": _dificultyIndex,
"targetMuscles": _targetMuscles,
"weekDays": indexList,
});
}
},
child: Container(height: 50, child: Center(child: Text("Next"))),
)
This works fine. It changes the _stepVals variable and _selectedIndex inside my main screen. It also changes to the widget to StepTwo(). But StepTwo widget is not taking the nw value of _stepVals. It appears it is using the initial value of _stepVals that it recieved inside initState. Am I missing something here? I'm new to the language so please any help is appreciated.
Upvotes: 1
Views: 86
Reputation: 516
You need to add this code to your setState
or above it to make it work:
setState(() {
// You only need this:
_pages = [
StepOne(_setSelectedIndex),
StepTwo(_stepVals, _setSelectedIndex)
];
// Or this:
_pages![1] = StepTwo(_stepVals, _setSelectedIndex);
_stepVals = {..._stepVals, ...newMap};
_selectedIndex = newIndex;
});
Because initState
isn't called when the widget rebuilds, it's only called on the first build of the widget, so you need to set the StepTwo
widget again to make it work.
ANOTHER WAY:
You can create a function like this:
Widget getStep(int index) {
switch (index) {
case 0:
return StepOne(index);
case 1:
return StepTwo(_stepVals, index);
}
}
Then add getStep
to your build
:
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.transparent,
),
body: Container(
margin: EdgeInsets.only(top: 10),
padding: EdgeInsets.symmetric(horizontal: 10),
child: getStep(_selectedIndex),
),
);
}
And use your setState
:
setState(() {
_stepVals = {..._stepVals, ...newMap};
_selectedIndex = newIndex;
});
You don't need to initState
any variable.
Upvotes: 3