I am new to Kivy and I wrote an App with 3 screens and a screenmanager. I want to use a mvvm (model-view-view-model pattern), so I want to have a ViewModel object that I add to each screen object. The below code gives me the following error:
text: root.view_model.get_some_text()
... AttributeError: 'ShowEmailScreen' object has no attribute 'view_model'
However, when I comment that out, the other directive that also uses view_model "on_release: root.view_model.set_cancel_lunch()" a few lines above in the kv file, is carried out without problem. So the view_model object must be there. I really can't wrap my head around this. Any help is appreciated.
class ShowEmailScreen(MDScreen):
def __init__(self, view_model, **kwargs):
super().__init__(**kwargs)
self.view_model = view_model
class ScreenManagement(ScreenManager):
def __init__(self, **kwargs):
super().__init__(**kwargs)
model = DataModel()
view_model = ViewModel(model)
main_screen = MainScreen(view_model, name='main_screen')
pick_date_screen = PickDateScreen(view_model, name='pick_date_screen')
show_email_screen = ShowEmailScreen(view_model, name='show_email_screen')
self.add_widget(main_screen)
self.add_widget(pick_date_screen)
self.add_widget(show_email_screen)
class ViewModel:
def __init__(self, model):
self.model = model
def get_some_text(self):
return('laskdfjfjd')
def set_cancel_lunch(self):
if self.model.cancel_lunch:
self.model.cancel_lunch=False
else:
self.model.cancel_lunch=True
class NoteApp(MDApp):
def build(self):
Builder.load_file("doctorsnote.kv")
self.screen_manager = ScreenManagement()
return self.screen_manager
if __name__=='__main__':
NoteApp().run()
And in doctorsnote.kv I have:
<ShowEmailScreen>:
id: PDS
md_bg_color: self.theme_cls.backgroundColor
MDBoxLayout:
orientation:'vertical'
MDBoxLayout:
MDButton:
on_release: root.view_model.set_cancel_lunch()
MDButtonText:
text: root.view_model.get_some_text()
The problem is that the line in your kv
:
text: root.view_model.get_some_text()
get executed before the view_model
is set in the ShowEmailScreen
. One way to handle that situation is to declare the view_model
as an ObjectProperty
in the ShowEmailScreen
:
class ShowEmailScreen(MDScreen):
view_model = ObjectProperty(None)
def __init__(self, view_model, **kwargs):
super().__init__(**kwargs)
self.view_model = view_model
Then use that Property
in the kv
file:
MDButtonText:
text: 'No View Model Yet' if not root.view_model else root.view_model.get_some_text()
Now the get_some_text()
method is not called until root.view_model
is not None
.