Creating a Mobile Web App with Vue, Vuetify & Typescript — Part 2

Creating a Mobile Web App with Vue, Vuetify & Typescript — Part 2We’re going to develop our News App further to show a list of news articles from server data and use Vuex for state management.

Jon KeepingBlockedUnblockFollowFollowingJan 28This article is the second part of the instalment.

If you haven’t read the first part, I recommend you start there and come back.

In this second part we’re going to see how to use the Vuetify card component and see how to use Vuex with modules.

The code for this article is available on the GitHub repo:https://github.

com/JonUK/vuetify-mobile-appNews List ComponentWe have the application shell in place for our News App and now we need to implement showing a list of news articles.

To help visualise how we want the UI to look, I’ve created a low-fidelity design using Adobe XD (a free version is available).

I’ve also used the free version of the Android GUI design kit from Great Simple Studio to start with a base of design elements.

Low-fidelity design for news articles listLooking through the Vuetify UI components, the card component is what we’re after to show each item in our list of news articles.

Vuetify has a 12 point grid system using Flexbox, so for each card, let's go with allocating 9 columns on the left for the news article title and the date string and go with 3 columns on the right for the article thumbnail.

Create a Vue Single File Component (SFC) called NewsList.

vue in the folder src/components folder.

This component contains markup for a single “hard-coded” news article.

Later we’ll come back to this component and dynamically populate it with data from the server.

Before that though, let's check the component is responsive by seeing how it renders at different mobile device viewport widths.

The layout works well on a typical mobile phone with a width of 375 device-independent pixels (DIPs) and looks reasonable even down to 320 DIPs, so we can be sure our app will look good across a range of mobile phone devices.

On the v-img component, we have set the srcset attribute to provide different sized versions of the same image to match with different pixel density devices.

High pixel density devices will download and display the larger image at the same allocated size, so will look nice and sharp.

On low pixel density devices, we won’t waste a user’s bandwidth with the larger image and instead the browser will download the normal sized image.

Server DataOur component is visually ready but still needs to be fed data from the server.

Let’s create an interface NewsArticle which will act as the contract for the data the news list component requires and create the related enum ArticleType.

Both these definitions will go into a new file src/types.

ts.

We could retrieve the server data from code in the news list component but this would give the component an additional responsibility above and beyond visually displaying data and could hinder the reuse of this component with different sources of data.

Having the component retrieve it’s own data would also add additional complexity when it comes to unit testing the component.

For these reasons, we’ll retrieve data from the server via a new service.

Create a new folder src/services and inside create the file newsService.

ts.

The method getArticlesByType retrieves all the articles from the static JSON file /data/articles.

json, filters them down to just the articles for the given ArticleType and then maps the server data into instances of an object that satisfy the interface NewsArticle.

In a real application, we’d want the server-side code to sort, filter and limit the results rather than do this client-side but we won’t concern ourselves with server-side code in this article.

Let’s use the news service in the top stories view component to retrieve the news articles and pass them to the news list component via a prop.

We need to add the newsArticles prop to the news list component to receive the articles.

The npm package vue-property-decorator (which Vue CLI already installed) provides improved TypeScript support for Vue props by providing a @Props decorator.

Let’s use this decorator in the news list component.

The exclamation mark after the property name (e.

g.

newsArticles!) indicates to the TypeScript compiler that while it won’t see the property being set to a value in our code, it should chill out and not worry about the value being undefined as it will be set.

In our case, Vue is providing the value when the component is created.

We now have a top stories view component that retrieves and displays news articles.

We can update the code examples and favourite view components in a similar manner to retrieve news articles via the news service and use the news list component to render the articles.

Top Toolbar TitleAs a user navigates between the different bottom navigation menu items, it would be nice if the top toolbar title changed to reflect the currently selected menu item.

To achieve this, we’re going to:Add some metadata to each route which will include the toolbar titleOn route change, update the toolbar title in a Vuex storeIn the top toolbar component, render the toolbar title from the Vuex storeLet’s start by looking a Vuex stores.

Vuex supports segregating stores into different modules which helps keep code organised and allows related state to be grouped together.

While our state requirements currently are very basic, we’re still going to use a Vuex store module.

With most non-trivial projects, it’s likely you’ll benefit from Vuex store modules so it’ll be good to see how to use them.

First we’ll define the types for the root state and the top toolbar state in the file types.

ts.

We’ll now create the top toolbar Vuex store module topToolbar.

ts in the folder src/store/modules.

The top toolbar store module contains the action changeTitle which in turn invokes the mutation setTitle.

The module also contains the getter title.

As we’re creating a Vuex store module, we’ll set namespaced: true which will keep our actions, mutations and getters out of the global namespace.

We now need to wire up the top toolbar store module with the existing store that the Vue CLI created for us.

Move store.

ts to the folder src/store and make the following changes.

Now in the router, we’ll update the top toolbar store and set the title during each route navigation.

Each route has a RouteMeta object associated with it and this object contains a title property.

In router.

beforeEach, we’re intercepting each route change, getting the metadata for the route and then invoking the top toolbar action changeTitle using the namespace topToolbar.

The function call to next lets Vuex know to continue proceeding with navigation.

The final step is to display the title in the top toolbar component using the title getter in top toolbar Vuex store.

The npm package vuex-class provides improved TypeScript support for Vuex getters by providing a @Getter decorator.

This package has not been installed by the Vue CLI so we’ll install this ourselves.

npm install vuex-class –saveWe can now use the @Getter decorator with the top toolbar title getter in the top toolbar component to show the title.

Take a step back and pat yourself on the back!.The Mobile Web App is taking shape nicely.

The code for this article is available on the GitHub repo:https://github.

com/JonUK/vuetify-mobile-app.

. More details

Leave a Reply