Hiya!
A little over two years ago, I started my journey into the world of Vue.js after a long and probably-never-ending stint with Angular. Working with Vue.js has been rewarding and there are more things to uncover even as work continues on the amazing framework and its libraries, e.g Nuxt.js.
Working with Angular gave me working TypeScript knowledge, but I (have) never tried to build anything with TypeScript outside Angular. I had to do a quick refresh on TypeScript with a scrimba course and toe-dipping into the Vue.js<>TypeScript world with this amazing YouTube playlist.
I am a huge TV shows fan, and I tweet a lot about my current favorites (follow me 🤩!), but I never thought about building an app to play around with TV shows data until now.
I built Moflixx with Angular sometime in 2019 but It was based on a Movies API. I wanted to build an application that would help me work with Vue.js (Composition API) and TypeScript and now felt like a great time to play around with some TV shows data.
The User Interface
Like Moflixx, I needed an API to fetch TV shows data from. It took a few days, but I found Episodate surprisingly off a series of GitHub search. I explored the data, it wasn't super robust in terms of endpoints available but It had everything I needed for TVFlixx
.
I needed some inspiration for the UI, but I did not also want to stray too far away from what my datasource website looked like, Episodate's interface pretty much did it for me, so I borrowed a few UI tips.
Next, I needed a structure for TVFlixx
. I wrote down a list of components and pages I felt I would need and sketched a few things as well for the components. A regular for me in this type of application is the Favorites
page.
Pages | Components |
---|---|
- TVShows
|
- Episodes
|
- NotFound / 404
|
- Pagination
|
- TVShowDetails
|
- Header
|
- Favorites
|
- TVShow
|
- TVShowList
|
|
- Loading component |
|
- Carousel
|
|
- CarouselItem component |
With the help of a few resources, I built some components I could have easily installed a few packages for.
For the next few paragraphs, I will explain the reasoning behind the choice of some components.
The TVShows
page is a simple page that shows a paginated list of TV shows from the API, 20 items are shown on each page depending on the items available from the API.
The TVShowDetails
page employs more of the other components.
For instance, I use the Carousel
and CarouselItem
components to show a list of images that comes with each TV show item - this helps any prospective user view the images one at a time or select any image from the preview.
I also use the Episodes
component in the TVShowDetails
page, the component takes an episodes
prop which is an array
of all the episodes contained in objects
for a particular TV show. This component filters each item in the array by their season and creates a view that enable users view list of episodes per season by selecting a button showing the season they are interested in.
The TVShow
component needed a few iterations before I could get what I wanted.
I wanted an hover effect to cause the card to flip to the other side to show some details and allow a user "see more details" about the TV show, took a while but I achieved it.
Front of card | Flip side |
---|---|
The other components are pretty much self-explanatory.
The TypeScript Part
I use the Volar
extension in my VS Code, so I had to enable the Template Interpolation Service
to do some validation and code completion in the template. I also wanted to explore the Composition API more and using the defineComponent
method from vue
was a good decision.
First, I knew I had to define the structure for the objects I would be using within the app. I created some interfaces to handle the data coming into each page and component and tried really hard to avoid the any
type 😅.
The Episodes
component required a special custom type different from the other interfaces I created, because it eventually provided an object of arrays
and the type for the key
for the items in the object weren't exactly known or constant before runtime as they were the values of the season
field for the episodes.
This extract from the TypeScript docs came in handy:
import Episode from "./Episode"
interface SeasonEpisodes {
[index: string]: Episode[]
}
export default SeasonEpisodes;
I also needed to handle issues around passing props to the components and ensuring the right type was enforced for the objects using type assertion with PropType
imported from vue
.
Conclusion
I use the composition API extensively at work, but using it with TypeScript encourages a bit more sanity within the codebase and data flow across components.
I will probably do some tweaks in the application (especially the UI) in the future but I really just wanted to focus on how I could work with the composition API and TypeScript.
I wanted to share my thoughts around working with TypeScript and Vue.js, this article mostly captures the parts I thought were worth talking about.
The Repository on GitHub - star the repo if you enjoyed this!
Thank you for reading.
Top comments (0)