Open timbell opened 10 months ago
That would work, though I try to keep Flutter out of my ViewModels as much as possible. (An exception is I typically put Flutter controllers in ViewModels). So, my approach would be to pass the params to ViewModel, rather than the Widget. So,
class MyViewWidget extends ViewWidget<MyViewModel> {
MyViewWidget({
super.key,
this.param1,
this.param2,
}) : super(builder: () => MyViewModel());
final int param1;
final String param2;
...
@override
void didUpdateWidget(covariant MyViewWidget oldWidget) {
super.didUpdateWidget(oldWidget);
viewModel.update(param1, param2);
}
...
}
class MyViewModel extends ViewModel {
...
void update(int param1, String param2) {
// Update ViewModel here to accommodate param changes
}
...
}
Apologies for the "viewModel not available" bug. I fixed and pushed this change just now, so if you upgrade to 1.5.3 you can use viewModel
in didUpdateWidget
.
Completely agree about keeping Flutter out of ViewModels! With the above you would need to pass the View parameters down in the ViewModel constructor as well to be able to handle the initial state. And this would imply duplicating the View parameters in the ViewModel unless I'm missing something?
What do you think about introducing a ViewParams
abstraction? Something like this in mvvm+ itself:
abstract class ViewParams {}
abstract class ViewWidget<T extends ViewModel> extends StatefulWidget
implements ViewParams {
...
}
class ViewState<T extends ViewModel> extends State<ViewWidget<T>>
with BilocatorStateImpl<T> {
...
T _buildViewModel() {
...
viewModel.viewParams = widget;
return viewModel;
}
@override
void didUpdateWidget(covariant ViewWidget<T> oldWidget) {
_viewModel.viewParams = widget;
_viewModel.didUpdateViewParams(oldWidget);
...
}
...
}
abstract class ViewModel<T extends ViewParams> extends Model {
...
late T viewParams; // setable in user code?
...
@protected
@mustCallSuper
void didUpdateViewParams(T oldViewParams) {}
}
Then in user code you could do:
abstract class MyViewParams implements ViewParams {
int get param1;
String get param2;
}
class MyViewWidget extends ViewWidget<MyViewModel>
implements MyViewParams {
MyViewWidget({
super.key,
this.param1,
this.param2,
}) : super(builder: () => MyViewModel());
@override
final int param1;
@override
final String param2;
...
}
class MyViewModel extends ViewModel<MyViewParams> {
// View parameters are accessed through the viewParams member
...
@override
void didUpdateViewParams(MyViewParams oldViewParams) {
// Update ViewModel here to accommodate ViewParams changes
}
}
Use of ViewParams would be optional, existing code would work as before
Currently I'm following this sort of pattern:
This works ok and more or less folllows what I think is the recommended way to do it vanilla Flutter.
So, my question: is this the intended way to access and handle changes to widget parameters from the view model?