If you are building a web application with the API-first approach, then you have to think of leveraging external APIs to execute part of your application logic. Single-page applications are a perfect candidate for building such Apps. These Apps allow the web browser to re-render different parts of the web page dynamically, by invoking APIs. These renders are independent of the entire web page and hence do not require a full reload of the page.
Over the last decade, single-page applications have gained much popularity, thanks to the underlying advancements in the browsers and the web protocols. Additionally, the API revolution has empowered developers with more options to define the business logic as API calls, instead of writing the logic themselves.
In this post, we are going to show you how to build a demo single page application (SPA) by leveraging the power of the RapidAPI’s API marketplace, on top of the Vue.JS framework. Vue.JS is an upcoming JavaScript framework for building modular, UI driven web applications. With this demo, you will learn about building a basic UI layout for the web application along with the intricacies of invoking the API and interacting with the UI elements through Vue.JS.
Choosing the Right API for Single Page Application
A single page application relies on AJAX calls to request the server for updates, even after the application is fully loaded. It typically follows this interaction sequence.
As a web developer, this is probably a no-brainer for you. However, depending upon the requirements of your application, the AJAX calls must be directed to appropriate external APIs to achieve the functionality of the App.
Let’s run through a hypothetical scenario to choose the best API from the RapidAPI marketplace.
Step 1: Signup for RapidAPI Account
To begin your API-First development journey, you’ll first need to sign up for a free RapidAPI developer account. With this account, you get a universal API Key to access all APIs hosted in RapidAPI.
RapidAPI is the world’s largest API marketplace, with over 10,000 APIs and a community of over 1,000,000 developers. Our goal is to help developers find and connect to APIs to help them build amazing apps.
With RapidAPI’s marketplace, you have many options to choose the best API for your single page application development requirements covering different industries, domains, and use cases.
Step 2: Discovering APIs
While choosing an APIs for your single page application project, you need to pay attention to your application requirements. Often, these requirements depend on a domain or specific expertise, which is otherwise challenging to code within your application.
Log into your RapidAPI account. The home page has many options to discover APIs as per your needs. You can either search for APIs based on a keyword, or choose from one of the predefined categories, and even select from the collection of top APIs for a given domain.
Let’s do a quick exercise to choose a good API for the development of our Vue.JS based single page application. Assuming that you want to build an App for a forex service, then your App frequently performs conversion from one currency to another. In the RapidAPI website, you can search for “currency”. Alternatively, you can look up the top currency converter and exchange APIs to get a curated list of top currency and exchange APIs hosted in the marketplace.
Step 3: Analysing the API
For each API, you can see the basic analytics about the popularity, latency, and its success rate. As an example, if you want to consider the Currency Value API, you can see its stats to get some idea about the API’s popularity & reliability.
Note that these stats change from time to time based on the API provider’s performance.
Step 4: Finalizing the API
Now, let’s get serious about the API selection. If you want to choose an API that has an excellent rating and maximum reliability, then take another look at the stats of all the API listed in the list of top currency and exchange APIs. Based on the performance of all APIs at the time of writing this article, you get two APIs that are performing well.
These are the Fixer Currency API and Currency Converter API. Both have a 100% success rate, which is very good for reliability, and both of them enjoy a popularity score of 9.8 out of 10. However, the Currency Converter API seems to have a latency of 78 ms, which is very, very low, and this means that the API is fast. On the other hand, the Fixer Currency API has a latency of 275ms, which is nearly four times more.
Considering this, the Currency Converter API should be your first choice. However, you should not fall for the latency values, as certain APIs are less complicated and hence tend to have less latency with the downside of having lesser accuracy.
If you read the description of both the APIs, then you will realize that Fixer Currency API relies on over 15 exchanges to give you the currency data. In contrast, the Currency Converter API does not make such claims. Considering that a normalized currency rate based on over fifteen exchanges would be a better bet, you can decide to go ahead with the Fixer Currency API.
As for the higher latency, a value of 275ms is not a bad number considering the average latencies of packet transfer across the Internet. Therefore, Fixer Currency API is our choice for powering the currency conversion within the forex conversion app.
Step 5: Subscribing to the API
With the API selection done, it’s time to test the API. Head over to the API console of Fixer Currency API.
Click on the “Pricing” tab and opt-in for the “Basic” subscription tier that gives you 1000 free API calls to Fixer Currency API per month.
Once subscribed, you can validate your subscription to this API. Take a look at the supported API endpoints of Fixer Currency API, at the left panel of the API console.
Select the “GET Supported Symbols” endpoint from the list of API endpoints. This API endpoint does not accept any input parameters, so you can directly invoke it by clicking the blue “Test Endpoint” button.
If you get an API response with a list of supported currencies, your subscription is now working.
Step 6: Validating the API
With the Fixer Currency API, you get a currency calculator directly built into the “GET Convert” API endpoint.
Select the endpoint and key in these values for the required parameters.
So, in this case, you are sending a request to the API to convert 1 US Dollar to 12 UAE Dirhams. Upon triggering, the API returns the response as follows.
Of course, the result of this API invocation varies based on the actual exchange rate at the time of invoking the API. That’s why you also get a timestamp in the API response.
This API endpoint is your best tool for undertaking any currency conversion tasks without the overheads of checking the exchange rates and doing any math. So you can directly use it within your single page application for forex conversion.
How to Build a Single-Page App (SPA) on Vue.JS
Now it’s time to leverage the Fixer Currency API to build the App. You are now going to build a rudimentary, single-page web application that performs currency conversion based on the “Get Convert” endpoint. This App leverages the Vue.js ecosystem to build the code from the grounds up.
Prerequisites
Before we start, let’s sort out the toolchain for this application. Make sure that you have installed the following.
1. Node & Npm: You must have the Node.JS and npm installed on your development computer. The latest packages are available on the official Node.js website.
2. Vue CLI: Vue CLI is used to set up the Vue project. You can install Vue CLI through the npm tool.
npm i -g @vue/cli
Steps for Building the Currency App with Vue CLI
We now embark on a live code walkthrough to build the app, one piece at a time.
1. Create a new Vue project
You start by creating an empty project directory. This directory is the root path where the project is created. Change to this directory and create an empty Vue project with the Vue CLI as follows.
vue create currency
This command asks for a few user inputs. Select the first option ‘none’, to set up the project with babel, router, vues and eslint. It will take some time to install all the dependencies. Finally, you should have a subdirectory named currency created within the root directory.
From the next step onwards, change to the currency/src subdirectory where all the source code of this Vue project will reside.
2. Create the Vue UI components
Now you have to create the main UI components of this single page application. The UI has two components, the main form, and History. The UI components are defined within the currency/src/components subdirectory.
After the new project creation, this subdirectory contains a sample ‘HelloWorld.vue’ component. Delete this file and define two new component files ‘Index.vue’ and ‘History.vue’.
currency/src/components/Index.vue
<template> <div id = "index"> <h1 id = "main-heading">Fixer Currency API Demo with Vue.JS</h1> <div id = "input-container"> <span class = "input-text">Convert</span> <select id = "from-currency" v-model = "fromCurrency"> <option value = "">Select currency</option> <option value = "USD">US Dollar (USD)</option> <option value = "GBP">Pound Sterling (GBP)</option> <option value = "EUR">Euro (EUR)</option> <option value = "AED">United Arab Emirates dirham (AED)</option> </select> <input type = "number" id = "amount" placeholder="Amount" v-model = "amount"> <span class = "input-text">To</span> <select id = "to-currency" v-model = "toCurrency"> <option value = "">Select currency</option> <option value = "AED">United Arab Emirates dirham (AED)</option> <option value = "EUR">Euro (EUR)</option> <option value = "GBP">Pound Sterling (GBP)</option> <option value = "USD">US Dollar (USD)</option> </select> <button type = "button" id = "convert-btn" @click = "clickConvert()">Convert</button> <!-- <button type = "button" id = "clear-btn" @click = "clear()">Clear</button> --> </div> <div id = "result-container" v-if = "convertClicked"> <h2 id = "result" v-if = "!loading"> <span id = "from-span">{{amount}} {{fromCurrency}}</span> = <span id = "to-span">{{result}} {{toCurrency}}</span> </h2> <h2 v-else>Loading...</h2> </div> <History v-if = "getHistory"/> </div> </template> <script> import History from './History' import { mapGetters } from 'vuex' export default { name: 'Index', components: { History, }, data() { return { apiKey: '<YOUR_RAPIDAPI_KEY>', fromCurrency: '', toCurrency: '', amount: 0, result: 0, convertClicked: false, loading: false, } }, methods: { clickConvert() { if(!(this.fromCurrency == '' || this.toCurrency == '' || (this.amount <= 0) || this.fromCurrency == this.toCurrency)) { this.convertClicked = true } this.convert() }, convert() { if(this.fromCurrency == '' || this.toCurrency == '' || (this.amount <= 0) || this.fromCurrency == this.toCurrency) { alert("Please check your inputs and try again") } else { this.loading = true let uri = 'https://fixer-fixer-currency-v1.p.rapidapi.com/convert?from=' + this.fromCurrency + '&to=' + this.toCurrency + '&amount=' + this.amount fetch(uri, { "method": "GET", "headers": { "x-rapidapi-host": "fixer-fixer-currency-v1.p.rapidapi.com", "x-rapidapi-key": this.apiKey } }) .then(response => { if(response.ok) { response.json() .then(response1 => { this.result = response1.result this.loading = false this.$store.commit('addToHistory',{fromCurrency: this.fromCurrency, toCurrency: this.toCurrency, amount: this.amount, result: this.result}) }) } }) .catch(err => { alert("There was a problem fetching the results. Please try again." + err) }) } }, clear() { this.amount = 0 this.fromCurrency = '' this.toCurrency = '' this.convertClicked = false } }, watch: { amount: function() { this.convertClicked = false }, fromCurrency: function() { this.convertClicked = false }, toCurrency: function() { this.convertClicked = false } }, computed: { ...mapGetters([ 'getHistory' ]) } } </script> <style scoped> @import url('https://fonts.googleapis.com/css?family=Sen&display=swap'); @import url('https://fonts.googleapis.com/css?family=Roboto&display=swap'); * { margin: 0; padding: 0; } #index { width: 80%; margin: auto; text-align: center; padding: 50px; } #main-heading { padding: 15px; border-bottom: 2px solid #000; width: 80%; margin: auto; font-family: 'Sen', sans-serif; } #input-container { padding: 30px; text-align: center; } #from-currency, #to-currency { border: 1px solid #ccc; padding: 10px; width: 150px; margin: 5px; } #amount { border: 1px solid #ccc; padding: 11px; } #result-container { padding: 15px; margin-top: 20px; font-family: 'Roboto', sans-serif; } #from-span { color: #DA3732; } #to-span { color: #008000; } #convert-btn, #clear-btn { padding: 11px 15px; border: none; color: #f4f4f4; margin-top: 15px; border-radius: 5px; } #convert-btn { background-color: #008000; color: #fff } #clear-btn { color: #000; } .input-text { font-family: 'Roboto', sans-serif; } @media screen and (max-width: 768px) { #index { width: 100%; padding: 10px; overflow-x: hidden !important; } #main-heading { width: 80%; font-size: 18px; margin: auto; } #input-container { padding: 5px; } #from-currency, #to-currency { display: block; text-align: center; width: 50%; margin: 10px auto; } .input-text { display: block; margin-top: 10px; } #amount { width: 45%; margin: auto; } } </style> |
Copy the above code and save it in the assigned subdirectory path as ‘Index.vue’ file. Also, ensure that you replace the placeholder <YOUR_RAPIDAPI_KEY> with your actual RapidAPI subscription key.
This code defines a Vue component that is responsible for managing the input-form, and displaying the result of currency conversion. All of this is contained in the <template> tag.
After this, the <script> block defines the component definition, along with the data, methods, and the watch keys for defining the critical interaction points with the UI. The most crucial method is convert( ) where the Fixer Currency API call is invoked, and the results are stored in a Vuex store. You will get to know more about Vuex store a bit later.
Finally, there is also the <style> tag for defining the CSS styling parameters for the UI.
Next, you have to create another component, called the ‘History.vue’.
currency/src/components/History.vue
<template> <div id="history"> <h2 id = "history-heading">History <i>(Last Five Operations)</i></h2> <table id = "history-table"> <tr> <th>From</th> <th>To</th> <th>Amount</th> <th>Result</th> </tr> <tr v-for = "(entry,index) in getHistory" :key = "index"> <td>{{entry.fromCurrency}}</td> <td>{{entry.toCurrency}}</td> <td>{{entry.amount}}</td> <td>{{entry.result}}</td> </tr> </table> </div> </template> <script> import {mapGetters} from 'vuex' export default { name: 'History', data() { return { } }, computed: { ...mapGetters([ 'getHistory' ]) } } </script> <style scoped> @import url('https://fonts.googleapis.com/css?family=Sen&display=swap'); @import url('https://fonts.googleapis.com/css?family=Roboto&display=swap'); #history { width: 90%; margin: auto; text-align: center; } #history-heading { font-family: 'Sen', sans-serif; } #history-table { width: 100%; margin: auto; text-align: center; border: 1px solid #000; } h4{ text-align: left; } th { font-family: 'Roboto' sans-serif; font-family: 22px; padding: 5px; border-bottom: 1px solid #000; } td { font-family: 'Sen', sans-serif; } </style> |
This one is a more straightforward component. It displays a table with the last five currency operations performed by the App. These are fetched from the Vuex store. There is no user interaction in this component.
The table gets updated every time a new currency conversion operation is initiated by the user. In this way, the App behaves like a true single page application, without reloading the entire web page.
3. Define the App route
Next up, you define the router so that Vue understands the URL endpoints for invoking the UI components. Ours is a simple App, which only has the one index path. Hence you can replace the content of the existing route definition as follows.
currency/src/router/index.js
import Index from '../components/Index' export default { mode: 'history', routes: [ { name: 'Index', path: '/', component: Index }, ] } |
4. Store the history of currency conversion operations
You have defined the ‘History.vue’ component earlier for displaying the results of the last five operations. Now, you need to define the underlying storage mechanism to contain the latest five operations performed in the App.
A Vuex store is like a shared container that stores the data shared by all components of a Vue app.
By default, there is a boilerplate ‘index.js’ file located in the src/store subdirectory. Open the file in an editor and replace the existing content with the following code.
currency/src/store/index.js
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state: { history: [], }, getters: { getHistory(state) { return state.history } }, mutations: { addToHistory(state, payload) { if(state.history.length < 5) { state.history.push(payload) } else { state.history.shift() state.history.push(payload) } }, }, actions: { }, modules: { } }) |
The Vuex container has predefined keys for setting state and defining the getter and setter functions for the store. In the case of this app, you need a getter function getHistory( ) and a setter function, defined within the mutations key, as addToHistory( ).
If you recall, the addToHistory( ) function is invoked within the ‘Index.vue’ component for adding the latest API response to Vuex store. Similarly, the getHistory( ) function is invoked by the ‘History.vue’ component for retrieving and displaying the history.
You can get the complete information about the concept of Vuex from the official tutorial.
5. Define the main component
The ‘App.vue’ file, located in src subdirectory is the top-level component of this application. It defines the main holding component for the two UI components that you defined earlier in step 2.
Replace the content of the existing ‘App.vue’ as follows.
currency/src/App.vue
<template> <div id="app"> <router-view/> </div> </template> <script> export default { name: 'App', } </script> <style> body { overflow-x: hidden !important; } #app { overflow-x: hidden !important; } </style> |
This file is self-explanatory. You define a top-level <div> element with the ‘id’ attribute set to ‘app’ and name set as ‘App’. Additionally, some basic styling is applied to set the overflow behavior of the component.
6. Define main.js for spawning the App
The ‘main.js’ file under src subdirectory is the first invocation point for launching the top-level App component for this application.
Replace the default content of ‘main.js’ as follows.
currency/src/main.js
import Vue from 'vue' import App from './App.vue' import store from './store' import VueRouter from 'vue-router' import routes from './router/index' Vue.config.productionTip = false Vue.use(VueRouter) new Vue({ store, router: new VueRouter(routes), render: function (h) { return h(App) } }).$mount('#app') |
This is the place to instantiate the main Vue object and pass it with store, router, and the top-level App component instances. It is the main entry point for launching the App.
With this file, you are now done with the development of this App.
7. Build & Run the App
The last step is to build and run the app. From the currency subdirectory, run the following command.
npm run serve
This will build the Vue project. If all goes well, then the build will succeed, and the command will launch a development server whose URL is displayed on your screen.
Summing Up With A Quick Test Of The Currency App
Fire up a web browser and launch the app with the URL of the development server. You can now play with the currencies and their values to get the instantly converted rates.
That brings up to the end of this demo on building a single page application with RapidAPI and Vue.JS. If you have any questions about integrating the APIs from RapidAPI in your Vue.JS App, then please send your queries in the comments below.
Leave a Reply