Accessing params in a widget's viewModel
Describe the bug
I built a widget, called OrbitWidget that also has a viewModel called OrbitViewModel. Since I didn’t want a route generated for this widget, I didn’t use stacked create view …, I just did a File New and extended the OrbitWidget with StackedView<OrbitalViewModel>.
I’m embedding the OrbitWidget into my SampleView. When a user navigates to the SampleView, the SampleViewModel gets graph data from our API which, in turn, gets fed as a parameter into the OrbitWidget(graphs: graphs). But, I’m having a hard time accessing the graph data from my OrbitViewModel. Can anyone tell me how to go about this? Here is what I have…
SampleView…
class SampleView extends StackedView<SampleViewModel> {
const SampleView({
Key? key,
}) : super(key: key);
@override
Widget builder(
BuildContext context,
SampleViewModel viewModel,
Widget? child,
) {
return OrbitWidget(graphs: viewModel.graphs);
}
}
SampleViewModel…
class SampleViewModel extends BaseViewModel {
List<Graph> graphs = await getGraphDataFromApi();
}
OrbitWidget…
class OrbitWidget extends StackedView<OrbitViewModel> {
final List<Graph> graphs;
const OrbitWidget({
Key? key,
required this.graphs,
}) : super(key: key);
@override
Widget builder(
BuildContext context,
OrbitViewModel viewModel,
Widget? child,
) {
print('OrbitWidget, graphs: ${graphs.length}'); // prints: OrbitWidget, graphs: 1
return DisplayGraphs(viewModel.graphs);
}
@override
OrbitViewModel viewModelBuilder(
BuildContext context,
) =>
// add graphs as a param to viewModel
OrbitViewModel(graphs: graphs);
}
OrbitViewModel…the viewModel has several functions which manipulates the data which is why I need access to it
class OrbitViewModel extends BaseViewModel {
// param
List<Graph> graphs;
OrbitViewModel({required this.graphs}) {
logger.i('OrbitViewModel, graphs: ${graphs.length}'); // prints: OrbitViewModel, graphs: 0
}
}
To reproduce
Expected behavior
No response
Screenshots
No response
Additional Context
No response
I fixed this by adding a key to OrbitalWidget, like so...
class SampleView extends StackedView<SampleViewModel> {
const SampleView({
Key? key,
}) : super(key: key);
@override
Widget builder(
BuildContext context,
SampleViewModel viewModel,
Widget? child,
) {
return OrbitWidget(
graphs: viewModel.graphs,
key: GlobalKey(),
);
}
}
Hi @pieterbergmans , how are you?
class SampleViewModel extends BaseViewModel {
List<Graph> graphs = await getGraphDataFromApi();
}
What is that ☝? You can't use a code like that. The await expression can only be used in an async function.
I would suggest to do something like below:
List<Graph> _graphs;
List<Graph> get graphs => _graphs;
Future<void> initialize() async {
_graphs = await getGraphDataFromApi();
}
Then, on the widget you access the graphs with viewModel.graphs but once is fetched, the Future has to be executed first for the graphs to be available, if not you only have a Future of something not the actual value.
@pieterbergmans Can this be closed?
@sebastianbuechler - yes, it can.