Modular Apps in MATLAB, Part 4: Creating a View or Controller That References a Model Class
From the series: Modular Apps in MATLAB
Learn how to utilize a model class with custom components or charts. This enables you to have modular, independent building blocks that will be utilized by a larger app.
Additional Resources:
Published: 30 May 2024
In this series, we're teaching modularization techniques to efficiently develop advanced applications in MATLAB and App Designer. Modularization will enable you to develop apps that are scalable, robust, testable and well-organized. I'm Robyn Jackey, Principal Consultant at MathWorks.
In our previous videos, Shawn discussed how to create a model class to store your data and algorithms. Then I explained custom components and charts. In this segment, I will explain how to combine these two concepts together, enabling you to break up a complex app into smaller modular components.
Some custom UI components or charts have data that are basic simple values. This color selector is a great example. It has just one simple data field-- the color value. You can change the color value from the component's edit box or from the button or from the command window.
But what if we're working with something much more complex? When the chart or component has multiple data fields, or even hierarchy, this is when you should encapsulate these related data properties into an object-oriented model class. Imagine we're tasked to design an app showing entries from a contact list or address book.
When your app needs to show the details of a particular person's contact information, it includes this component. This contact view enables you to also edit the contact. It's an example of a hybrid view controller component, since it both displays information from the model and allows the user to modify model properties.
Hybrid view controller components are common in advanced MATLAB application development workflows. Back in part 2 of this series, Shawn demonstrated the Contact class, a model for this component here that presents the view of a contact. It contains the relevant fields for an individual contact, storing things like the person's name, phone number, and address.
I've made Contact a handle class, meaning that one instance of a contact can be referenced from multiple places. A handle class lets you have multiple different variables that refer to the same data. For example, if I create another reference to the contact instance and then I change the data from this reference, the updates are reflected in the underlying Contact object and other references to it.
When I design a custom component to be the view of this contact, where contact is a handle class, the view will reference an instance of this Contact object that could be utilized or modified elsewhere, such as the Command window or an additional view or control component elsewhere in your app. Let's create this Contact view.
I'm going to first create a figure and then place the Contact view into a layout. Now, if I would create this Contact view without providing it a parent, it would just pop up in a new figure. Be aware of that in your code if you start seeing random figure windows appearing.
The component runs its update method at the end of construction. And initially, the contact is empty. So the view just presents disabled fields. Let's create a new contact now. And we will attach it to the view.
The component's update method pulls the contact's fields into the view to display the values. If I edit a field in this view controller, a callback updates the value in the model class. Now I make a second contact. And I tell the view to reference this contact instead.
The component sees that a property change occurred. And the update is triggered. But what if I change the Name property within this existing Contact instance that's already being displayed? Here, we do not see any change in the view. Why?
In part 2 of this series, Shawn explained how the view needs to listen to changes in the model class. This way, when something in the model changes, the view will know to update itself. To enable the contact list component to listen to changes in the model, we need to mark the relevant contact model properties as SetObservable. Then we need to listen to these properties.
One way to do this is to add listeners to the view component. When we attach a contact to this view, the view creates listeners to each of the relevant properties. So if we change an observable property inside the model, the listener triggers an update to happen.
Now, there are some advanced situations here that you should know about. First, the top-level model class should always be a handle. In this case, Contact is my model. However, you can use value classes within the model class, such as the Address class here, that is aggregated inside the model class Contact.
In situation two, what if the Address class inside Contact is also a handle class? So we have handle classes nested inside other handle classes. These two situations make listening for changes a bit different. There are strategies for these situations. But I'm not going into that level of complexity in this video.
So in review, I've shown you how you can connect a model to a view component using the custom component capability. A custom chart can also be composed as a view and then connected to a model in the same way I just showed. Using these techniques, you can take large, complex applications and break them down into manageable modular pieces and then pull these pieces together to build the complete app.
This is modular application development using model-view-controller architecture in MATLAB. It enables your work to be efficient, robust and scalable. For more information about building apps in MATLAB, check out the links in the description. You can also sign up for our professional training classes and get engaged with a consultant, like me, to help ensure you're optimizing your own app designs. Thanks for watching.