Part 6 - Build Steem blockchain application with Vue.js: input forms and handling REST API callssteemCreated with Sketch.

in #utopian-io5 years ago

Repository

Vue.js: https://github.com/vuejs/vue

What Will I Learn?

  • How to implement input form in Vue.js
  • How to handle REST API calls in Vue.js

Requirements

  • A Node.js environment (Ubuntu 18 + Node.js is used in this tutorial)
  • Basic HTML/CSS/Javascript knowledge

Difficulty

Basic level

Tutorial contents

In last tutorial, passing information between components, state management in Vuex, and vuex-persist were discussed. In this tutorial, various aspects to implement an input form in Vue.js will be discussed. In addition, how to handle REST API calls in Vue.js will be demonstrated.

Implement input forms in Vue.js

In this section, a new form to post content to Steem blockchain will be added and the underlying features, e.g. data binding, validation check and event handling will be implemented in the Vue.js way.

Add basic HTML form

First, add a new component, e.g. components/NewPost.vue. Within this component, add the following into the “template” section:

<template>
  <div class="post_form">
    <h4>New post</h4>

    <div class="row post_field">
      <div class="col-sm-3 col-xs-12">
        Username
      </div>
      <div class="col-sm-9 col-xs-12">
        **Username**
      </div>
    </div>
    <br/>
    <div class="row post_field">
      <div class="col-sm-3 col-xs-12">
        Posting key
      </div>
      <div class="col-sm-9 col-xs-12">
        <input type="password" class="form-control" id="postingKey">
      </div>
    </div>
    <br/>
    <div class="row post_field">
      <div class="col-sm-3 col-xs-12">
        Title
      </div>
      <div class="col-sm-9 col-xs-12">
        <input type="text" class="form-control" id="postTitle" placeholder="Enter post title">
      </div>
    </div>
    <br/>
    <div class="row post_field">
      <div class="col-sm-3 col-xs-12">
        Content
      </div>
      <div class="col-sm-9 col-xs-12">
        <textarea class="form-control" id="postContent" row="10"></textarea>
      </div>
    </div>
    <br/>
    <div class="row post_field">
      <div class="col-sm-3 col-xs-12">
        Category
      </div>
      <div class="col-sm-9 col-xs-12">
        <input type="text" class="form-control" id="category">
      </div>
    </div>
    <br/>
    <div class="row">
      <div class="col-sm-12 col-xs-12">
        <button>Submit</button>
      </div>
    </div>
    <br/>
  </div>
</template>

The form should look like:

Add data attributes and link them to HTML elements

username

As discussed in previous tutorials, username is defined/managed in ‘User’ mixin, so ‘User’ mixin needs to be imported into this component, e.g.

import User from './mixins/user'

And the component should be defined like:

export default {
  name: 'NewPost',
  mixins: [User]
  ......
}

So the username part in the template can be changed to:

<div class="col-sm-9 col-xs-12">
  {{username}}
</div>

Other data attributes and link them to HTML elements

To match with the fields defined in the template, the following data attributes need to be defined in the component code:

data () {
  return {
    posting_key: '',
    title: '',
    content: '',
    category: ''
  }
},

In the above code, ‘posting_key’, ‘title’, ‘content’, and ‘category’ link to the HTML tags in the template. By using ‘v-model’, the HTML tags in the template can be refactored to:

<input v-model="posting_key" type="password" class="form-control" id="postingKey">
......
<input v-model="title" type="text" class="form-control" id="postTitle" placeholder="Enter post title">
......
<textarea v-model="content" class="form-control" id="postContent" row="10"></textarea>
......
<input v-model="category" type="text" class="form-control" id="category">

The above code means, as long as user entered data in the HTML fields, the associated data attributes will be updated automatically.

Data validation

To validate the form inputs, a data attribute needs to be added first, e.g.

data () {
  return {
    ......
    errors: []
  }
},

Then, ‘v-on:click’ can be used to register an event handler, e.g. “submit” function to handle the click events:

<button v-on:click="submit">Submit</button>

The implementation of ‘submit’ method is as shown below:

methods: {
  submit () {
    let valid = true

    if (!this.username) {
      this.errors.push('Username required.')
      valid = false
    }
    if (!this.posting_key) {
      this.errors.push('Posting key required.')
      valid = false
    }
    if (!this.title) {
      this.errors.push('Title required.')
      valid = false
    }
    if (!this.content) {
      this.errors.push('Content required.')
      valid = false
    }
    if (valid === false) {
      return
    }
  }  
}

From the code above, whenever an invalid input value is found, an error message is pushed into the array.

Now it is the time to display the error message. Add the following code into the template:

<div v-if="errors.length" class="row error_field">
  <div class="col-sm-12 col-xs-12">
    <b>Please correct the following error(s):</b>
    <ul>
      <li v-for="error in errors" :key="error">{{ error }}</li>
    </ul>
  </div>
</div>

The above code checks if there is any messages in the data attribute “errors”. If any messages exist, use ‘v-for’ to show all messages in an unordered list. If any required fields are missing, the page should look like:

This example demonstrate one of the fundamental feature of Vue.js: developers do not need to update DOM - they just need to manipulate the data.

Post to Steem blockchain

Once the data validation is passed, it is the time to post to Steem blockchain. For demo purpose, this application only provides very basic functionalities, e.g. only main category is supported. More fancy features can be added later.

The following code can be added to post an article to Steem blockchain:

steem.broadcast.comment(
  this.posting_key,
  '',
  this.category,
  this.username,
  new Date().toISOString().replace(/[^a-zA-Z0-9]+/g, '').toLowerCase(),
  this.title,
  this.content,
  { tags: [this.category], app: 'utopian-test/aafeng' },
  function (err, result) {
    if (err) {
      alert('Failure! ' + err)
    } else {
      alert('Success!')
    }
  }
)

Once the post is published, a popup window confirms that the post operation has been successfully, as shown below:

Steemd.com can be used to check if the post properties have been submitted properly, e.g. for the demo post:

Add ‘New post’ button in Posts component

A ‘New post’ button needs to be added to navigate users to the new post form. To do so, first add the button to template part of components/Posts.vue:

<div class="row post_new">
  <button v-on:click="newPost">New post</button>
</div>

In the newPost method, the route needs to be updated, as shown in the following code:

newPost () {
  // Update Vue.js route
  this.$router.push({ path: '/@' + this.username + '/new_post' })
}

By this way, users are able to use the ‘NewPost’ component:

Handling REST APIs with axios

Nowadays, it is very common to have a pure client side application working with RESTful APIs. How to use axios to make calls to REST APIs, and how to handle responses in Vue.js will be discussed in this section. Poloniex’s price ticker API will be used for demonstration.

Install axios

The installation of axios is very easy, just run this command:

npm install --save axios

Create SteemPrice component

Add a new file, e.g. components/SteemPrice.vue which will make REST API calls via axios and display current STEEM/SBD price pairs within the component.

<script>
let axios = require('axios')

export default {
  name: 'SteemPrice',
  data () {
    return {
      info: ''
    }
  }
}
</script>  

In the above code, a data attribute, e.g. ‘info’ is used to store the price pairs.

Send request to poloniex REST API

Poloniex REST API will be used in the demo application. The poloniex REST API endpoint is: https://poloniex.com/public?command=returnTicker. Open a browser and enter the above URL in the address bar then hit ‘Enter’, the result will be presented with JSON format:

While the SteemPrice component is loaded, some additional work needs to be done to make the REST API call and parse the returned JSON data and store it in the data attribute ‘info’. The code is shown as follows:

mounted () {
  let priceComponent = this
  // Make poloniex REST API call
  axios.get('https://poloniex.com/public?command=returnTicker')
    .then(function (response) {
      for (let p in response['data']) {
        // only store STEEM/SBD price pairs
        if (p.endsWith('_STEEM') || p.endsWith('_SBD')) { 
          priceComponent.prices = priceComponent.prices + p + ': ' + response['data'][p]['last'] + '/'
        }
      }
    })
    .catch(function (error) {
      console.log(error)
    })
}

In this application, only ‘STEEM’ and ‘SBD’ price pairs will be displayed, so some processing logic has been added into the above code.

To display the returned price pairs, add the following code to the template:

<div class="row" v-for="p in prices.split('/')" :key="p">
  <div class="col-sm-12">
    {{p}}
  </div>
</div>

The page looks like:

To make other REST API calls, please read axios documentation for more information.

Curriculum

This is the 6th tutorial.

Previous tutorials

Part 1 - Build Steem blockchain application with Vue.js: installation and first demo
Part 2 - Build Steem blockchain application with Vue.js: components, computed properties and build/deployment process
Part 3 - Build Steem blockchain application with Vue.js: using Bootstrap, nav component, mixins, and first iteration of Posts component
Part 4 - Build Steem blockchain application with Vue.js: dynamic route, and event handling
Part 5 - Build Steem blockchain application with Vue.js: Passing data among components, state management via Vuex, and data persistent in Vue.js

Proof of Work Done

Source code for this tutorial: https://github.com/aa-feng/VuejsTutorial/tree/t06

Master branch of the source code (will be updated with ongoing tutorials): https://github.com/aa-feng/VuejsTutorial

The live demo of latest iteration: https://vuetutorials.aafeng.top

Sort:  

Thank you for your contribution @aafeng.
We've been reviewing your tutorial and suggest the following points below:

  • Tutorial very well structured and explained.

  • Basic HTML code does not need to be presented in the tutorial. The reader can check on your proof of work.

  • We really like the possibility of seeing the demo. It is very important for readers, they can experiment and see how the features that you have developed work.

  • Why didn't you use the required parameter in the HTML code?For example:

<input v-model="posting_key" type="password" class="form-control" id="postingKey" required>


Thank you for your work in developing this tutorial.
Looking forward to your upcoming tutorials.

Your contribution has been evaluated according to Utopian policies and guidelines, as well as a predefined set of questions pertaining to the category.

To view those questions and the relevant answers related to your post, click here.


Need help? Chat with us on Discord.

[utopian-moderator]

Thanks for your suggestions. Yes, you are right, 'required' can be use to do basic checks while more complex checks can be implemented in Vue.js

Thank you for your review, @portugalcoin! Keep up the good work!

Hi, @aafeng!

You just got a 0.9% upvote from SteemPlus!
To get higher upvotes, earn more SteemPlus Points (SPP). On your Steemit wallet, check your SPP balance and click on "How to earn SPP?" to find out all the ways to earn.
If you're not using SteemPlus yet, please check our last posts in here to see the many ways in which SteemPlus can improve your Steem experience on Steemit and Busy.

Hi @aafeng!

Your post was upvoted by @steem-ua, new Steem dApp, using UserAuthority for algorithmic post curation!
Your post is eligible for our upvote, thanks to our collaboration with @utopian-io!
Feel free to join our @steem-ua Discord server

Hey, @aafeng!

Thanks for contributing on Utopian.
We’re already looking forward to your next contribution!

Get higher incentives and support Utopian.io!
Simply set @utopian.pay as a 5% (or higher) payout beneficiary on your contribution post (via SteemPlus or Steeditor).

Want to chat? Join us on Discord https://discord.gg/h52nFrV.

Vote for Utopian Witness!

Congratulations @aafeng! You have completed the following achievement on the Steem blockchain and have been rewarded with new badge(s) :

You received more than 5000 as payout for your posts. Your next target is to reach a total payout of 6000

You can view your badges on your Steem Board and compare to others on the Steem Ranking
If you no longer want to receive notifications, reply to this comment with the word STOP

To support your work, I also upvoted your post!

Do not miss the last post from @steemitboard:

Are you a DrugWars early adopter? Benvenuto in famiglia!
Vote for @Steemitboard as a witness to get one more award and increased upvotes!

Coin Marketplace

STEEM 0.26
TRX 0.11
JST 0.033
BTC 64207.05
ETH 3065.15
USDT 1.00
SBD 3.87