Tuesday, October 23, 2018

Part 5 - Linking ViewModels to your Mobile App

This is part 5 of a multi-part tutorial of building a mobile application step by step from start to finish.  If you have just landed here, I encourage you to take the journey with me through building a mobile application.  I’ll show you how easy it is to build and maintain an application that can be hosted as a web application as well as a mobile application.  If you are here for part 5, we’re ready to discuss ViewModels.

The main goals I have for using ViewModels between the client and server is to limit complexity and overexposure of data on the client side.  The ViewModel will be an object (or data model) that supports the user interface (or view); thus a View-Model.  Our ViewModels will exist on the client and server side applications and make the transmission of data between the client and server seamless.  If you are familiar with other methods, like mapping, exposing models directly, or sending complex composite objects, I recommend giving simple ViewModels a try.  They may seem like more work, but they provide clarity, consistency, and security that is difficult otherwise to achieve.
With all of that being said, let’s get to business with our first ViewModel.

Open Visual Studio Code to the invoicing application we have been working on and create a new folder called view-models under the src folder.

The first ViewModel we’ll create will be for the Login screen (src/pages/home/home.html).  If you recall, this page includes an email address input and a password input.

Right-click on the view-models folder and add a New File and name the file LoginViewModel.ts.  We’ll add the two fields that we need to accept input from on the login screen itself.  These should both be the String data type.

image

src/view-models/LoginViewModel.ts
image

Let’s now connect this up to our login component.  There are two ways to connect or bind to components.  We’ll be covering the more straight forward ngModel binding method.  Save your ViewModel and open the src/pages/home/home.ts file.

Add a property before the constructor to hold an object reference to the new ViewModel that we just created.  Using the intellisense, you can get the appropriate imports with little effort.

src/pages/home/home.ts
image

Next we’ll implement the interface named OnInit.  Type “implements OnInit” in the class declaration as shown below.  The intellisense will add OnInit to the top import and you will be required to implement this interface by creating an ngOnInit() { } method.  If you aren’t familiar with the dynamics of interfaces, you may want to do a quick google search.  The ngOnInit method will be executed automatically during the creation of the login component as part of the component’s life cycle.

image

We’ll then create our LoginViewModel object to populate our loginData property.

image

Using the ngOnInit() method in this case may be overkill, but this should be used when we start pulling data from the server.  This will allow the page to begin loading while data is being requested from the server and this should be the standard place we request data when a component is loaded.  To make sure the data is captured accurately from the form, let’s log the object in the Login button.  Add a simple console.log call in the login method as shown below.

image

Next, we’ll bind the inputs to the loginData object reference.  Open the src/pages/home/home.html file so we can add the data bindings.  On the email and password <ion-input> components we’ll add a binding attribute for ngModel.  To do this, add [(ngModel)]="property.field" to each of the inputs.  The "[ ]"s indicate property binding and the "( )"s indicate event binding.  In this case, the property is the value of the input box (like if we were pre-populating it), and the event is when something is typed into the input box such that our property values are updated.  I also made one additional change to the "type" property of the password input.  I changed the type to "password" such that any input is masked as it is typed.

image

Let’s run the application now to ensure the binding worked as expected.  Pull up the terminal with CTRL + Shift + ~ and type "ionic serve" to start the application.

image

Before clicking the Login button, press F12 to pull up the browser’s console window so we can see the loginData object that we had added code to log.  As you can see below, it logged the object as we expect.

image

As we continue on the other Views and create our ViewModels, we should include an "Id" numeric field such that we can identify and save any changes back to the database once the data has been delivered.  There is no need to create a ViewModel for a list of other ViewModels at this time, so we’ll only need a ClientViewModel and an InvoiceViewModel.  We may want to create a separate object in the future to optimize this listing.

src/view-models/ClientViewModel.ts
image

src/view-models/InvoiceViewModel.ts
image

Now, lets link these to the Views.

src/pages/client-detail/client-detail.ts (Add property, implement OnInit, add ngOnInit(), create new object)
image

src/pages/client-detail/client-detail.html (Add ngModel bindings to each input)
image

src/pages/invoice-detail/invoice-detail.ts
image

src/pages/invoice-detail/invoice-detail.html (only showing a subsection below)
image

For the Client List and Invoice List, we’ll populate some sample data so we can see that the list still works.  We’ll create an array of view models for each and populate it with the sample data and then use the *ngFor directive to repeat the <ion-item> component for each of the items in our array.

src/pages/client-list/client-list.ts
image

src/pages/client-list/client-list.html
image

src/pages/invoice-list/invoice-list.ts
image

src/pages/invoice-list/invoice-list.html
image

Restart the application and make sure everything is working as expected.

Now that we have the application in a somewhat working state, let’s have some fun and deploy it to an Android device in the next post.  A Mac is required for Apple deployment, so I will wait until the application is closer to production ready prior to running through this process.

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.