HTML forms can send an HTTP request declaratively while submitting forms and awaiting response. However, you have to wait for a full page reload before getting your results, which most times is not the best user experience.
Forms can also prepare an HTTP request to send via JavaScript, which makes for a better user experience. This article explores ways to do that using three different frameworks: Vue, React, and Hyperapp.
Submitting forms using Vue
Vue is a progressive framework for building user interfaces. Unlike other monolithic frameworks, Vue is designed from the ground up to be incrementally adoptable. To learn more about Vue, you can visit the official homepage here.
First, let’s define our HTML structure. Create a file named vue.html
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css"> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> <div class="container" id="app"> <div class="row"> <div class="col-md-4"> <div class="panel"> <h4 class="heading"><strong>Quick </strong> Contact <span></span></h4> <div class="form"> <input type="text" required="" placeholder="Please input your Name" value="" v-model="form.name" class="form-control"> <input type="text" required="" placeholder="Please input your mobile No" value="" v-model="form.mob" class="form-control"> <input type="text" required="" placeholder="Please input your Email" value="" v-model="form.email" class="form-control"> <textarea placeholder="Your Message" v-model="form.mess" class="form-control"></textarea> <input type="submit" value="submit" name="submit" class="btn btn-primary" @click="submitForm()"> </div> </div> </div> </div> </div>
The code snippet above is a basic HTML declaration in which we:
- Required the Bootstrap CSS library
- Required the Vue JavaScript library
- Required the Axios JavaScript library, this library would make
POST
requests. - Declared 5 elements which comprise 3 input text boxes, one text area, and one button, which would be used to submit the form.
You would notice that in each of the 5 elements, the first 4 declares a v-model
attribute to some certain properties of form
.
V-model
is a way of binding inputs to Vue, such that Vue has the values of these input as they change.
Form
does not refer to the HTML form, but refers to an object which we have used for the binding in our Vue component.
Last, if you look at the button element, you would notice a little directive called @click
. This directive binds the click event of the button to Vue, instructing Vue on what to do when the button is clicked.
Implementing Vue into the form
In the previous section, we have explained the reason you have seen attributes like v-model
in your HTML structure and the @click
directive. Here, we show what the Vue part that handles the rest looks like.
Open a script file in your HTML document and paste in:
<script> var app = new Vue({ el: '#app', data: { form: { name: '', mob: '', email: '', mess: '' } }, methods: { submitForm: function(){ axios.post('https://httpbin.org/anything', this.form) .then(function (response) { console.log(response.data); }) .catch(function (error) { console.log(error); }); } } }) </script>
In the code block above, we defined an Object called form, which comprises our data. Next, we defined a method called submitForm
which does an Ajax request to https://httpbin.org/anything
. We use httpbin because their service allows us to perform free HTTP methods. The /anything
route would return the exact data which we had sent to it.
See how easy it is to submit a form using JavaScript? all you need do is change the URL to that of your server.
Why is my Form is not submitting? Often we note that after writing what looks like the right piece of code, the form does not submit. How do we troubleshoot this? Let me highlight common reasons your Vue form might not submit.
- The mounted element with the id of
app
passed into the Vue object with theel
key does not exist, and the app is not bound to Vue - The click handler on the submit button does not exist/was not attached
- The axios library was not referenced
- The Vue library was not referenced
Submitting forms using React
React is a JavaScript library for building user interfaces developed and maintained by Facebook. React makes it painless to create interactive UIs. Design simple views for each state in your application and React will efficiently update and render just the right components when your data changes.
First, let’s define our HTML structure. Create a file named react.html
and add:
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css"> <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> <div class="container" id="app"> </div>
The code snippet above is a basic HTML declaration in which we:
- Required the Bootstrap CSS library
- Required the React JavaScript library
- Required the React-Dom JavaScript library
- Required the Axios JavaScript library, this library would make
POST
requests - Declared a div with the id of
app
, which would be our root component
Implementing React into the mix
We have a basic setup with the required libraries available and a root element which react would be attached to. Let’s go ahead with the react implementation. Open a script tag and input:
class Root extends React.Component { constructor(props) { super(props); this.state = { form: { name: "", mob: "", email: "", mess: "" } }; this._onInputChange = this._onInputChange.bind(this); this._onSubmit = this._onSubmit.bind(this); } _onInputChange(name, e) { var form = this.state.form; form[name] = e.target.value; this.setState(form); } _onSubmit() { axios .post("https://httpbin.org/anything", this.state.form) .then(function(response) { console.log(response.data); }) .catch(function(error) { console.log(error); }); } render() { return ( <div className="row"> <div className="col-md-4"> <div className="panel"> <h4 className="heading"> <strong>Quick </strong> Contact <span /> </h4> <div className="form"> <input type="text" required="" placeholder="Please input your Name" className="form-control" onChange={e => this._onInputChange("name", e)} /> <input type="text" required="" placeholder="Please input your mobile No" className="form-control" onChange={e => this._onInputChange("mob", e)} /> <input type="text" required="" placeholder="Please input your Email" onChange={e => this._onInputChange("email", e)} className="form-control" /> <textarea placeholder="Your Message" className="form-control" onChange={e => this._onInputChange("mess", e)} /> <input type="submit" value="submit" name="submit" className="btn btn-primary" onClick={this._onSubmit} /> </div> </div> </div> </div> ); } } ReactDOM.render(<Root />, document.getElementById("app"));
Let’s take a review of what we have above. Here, in our constructor, we declared an initial state that comprises our form object, we then moved ahead to bind two functions which we will set the state as the input changes and submit the form.
In the _onInputChange
function, we receive two arguments, which are:
- name: the name of the element
- event: the change event that occurred
We use this two parameters to set the state of the exact input that was changed.
In the _onSubmit
function, we fire a post request to the https://httpbin.org/anything
endpoint, which returns the exact parameters sent. Here, which is what we use as our server.
Let us take a critical look at the render
function, where the elements are being rendered.
Here, we defined 5 elements, which comprise 3 inputs, a text area whose change events are bound to the _onInputChange
function, and a button element, whose click event is bound to the _onSubmit
method.
Finally, we attached the app to an element on our HTML markup.
Why is my Form not displaying? I bet you have been getting a blank screen and cannot understand where the error is coming from.
More great articles from LogRocket:
- Don't miss a moment with The Replay, a curated newsletter from LogRocket
- Learn how LogRocket's Galileo cuts through the noise to proactively resolve issues in your app
- Use React's useEffect to optimize your application's performance
- Switch between multiple versions of Node
- Discover how to use the React children prop with TypeScript
- Explore creating a custom mouse cursor with CSS
- Advisory boards aren’t just for executives. Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Taking a quick look at the render function, you would notice we have jsx
syntax in there. Now, here is the catch. Unless you are using babel to compile your app, jsx
would most likely fail. This is because jsx
isn’t regular javascript syntax, and here, we are using the browser build of React.
So how do we solve this? It’s a simple fix.
Any JSX block can be converted into a call to React.createElement
with three arguments:
- The element to create, e.g
div
,span
,ul
, e.t.c. - A properties object which specifies any property values to be set on that element e.g
class
,style
,required
, e.t.c. - Any child elements to place in it. This could be a string or other calls to
React.createElement
to get more elements.
Replace the render function with this:
render() { return ( React.createElement("div", { className: 'row' }, [ React.createElement("div", { className: 'col-md-4' }, [ React.createElement("div", { className: 'panel' }, [ React.createElement("h4", {}, 'Quick Contact'), React.createElement("div", { className: 'form' }, [ React.createElement("input", { type: 'text', placeholder: "Please input your Name", className: "form-control", name: 'name', onChange: (e) => this._onInputChange('name', e) }), React.createElement("input", { type: 'text', placeholder: "Please input your Mobile number", className: "form-control", name: 'mob', onChange: (e) => this._onInputChange('mob', e) }), React.createElement("input", { type: 'text', placeholder: "Please input your Email", className: "form-control", name: 'email', onChange: (e) => this._onInputChange('email', e) }), React.createElement("textarea", { placeholder: "Please your message", className: "form-control", name: 'mess', onChange: (e) => this._onInputChange('mess', e) }), React.createElement("button", { type: 'button', className: "btn btn-primary", onClick: () => this._onSubmit() }, "submit"), ]) ]) ]), ]) ); }
Also, update the ReactDom.render
call to this:
ReactDOM.render( React.createElement(Root, null), document.getElementById('app') );
Why is my form not submitting? Even after performing each step we think is necessary and cross-checking our code, it is possible your form does not still submit, how do we trouble-shoot this?
- Ensure that your console is not throwing up errors
- Ensure that the click and change events are bounded correctly
- Cross check that the
axios
library or the library you use for post requests is referenced
Submitting forms using HyperApp
HyperApp is a JavaScript micro-framework for building web applications. This framework has aggressively minimized the concepts you need to understand to be productive while remaining on par with what other frameworks can do.
HyperApp holds firm on the functional programming front when managing your state, but takes a pragmatic approach to allowing for side effects, asynchronous actions, and DOM manipulations.
First, let’s define our HTML structure. Create a file named hyper.html
and add:
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css"> <script src="https://unpkg.com/hyperapp"></script> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> <div class="container" id="app"> </div>
The code snippet above is a basic HTML declaration in which we:
- Required the Bootstrap CSS library
- Required the Hyperapp JavaScript library
- Required the Axios JavaScript library, this library would make
POST
requests - Declared a div with the id of
app
, which would be our root component
Introducing Hyperapp to the app We have a basic setup with the required libraries available and a root element which HyperApp would be attached to. Let’s go ahead with the react implementation. Open a script tag and input:
const h = hyperapp.h; const app = hyperapp.app; const state = { form: { name: '', mob: '', email: '', mess: '', } } const actions = { onInputChange: (event) => state => { state.form[event.target.name] = event.target.value; return state; }, submitForm: () => { console.log(state.form) axios.post('https://httpbin.org/anything', state.form) .then(function (response) { console.log(response.data); }) .catch(function (error) { console.log(error); }); } } const view = (state, actions) => ( h("div", {class: 'row'}, [ h("div", {class: 'col-md-4'}, [ h("div", {class: 'panel'}, [ h("h4", {}, 'Quick Contact'), h("div", {class: 'form'}, [ h("input", {type: 'text', placeholder: "Please input your Name", class:"form-control", name: 'name', oninput: (e)=>actions.onInputChange(e)}), h("input", {type: 'text', placeholder: "Please input your Mobile number", class:"form-control", name: 'mob', oninput: (e)=>actions.onInputChange(e)}), h("input", {type: 'text', placeholder: "Please input your Email", class:"form-control", name: 'email', oninput: (e)=>actions.onInputChange(e)}), h("textarea", {placeholder: "Please your message", class:"form-control", name: 'mess', oninput: (e)=>actions.onInputChange( e)}), h("button", {type: 'button', class:"btn btn-primary", onclick: ()=>actions.submitForm()}, "submit"), ]) ]) ]), ]) ) app(state, actions, view, document.getElementById('app'))
Let’s take a review of what we have above. Here, we declared an initial state that comprises our form object, we then moved ahead to declare two actions which we will set the state as the input changes and submit the form.
In the onInputChange
function, we receive one argument, which is:
- event: the change event that occurred
We use this two parameters to set the state of the exact input that was changed.
In the _onSubmit
function, we fire a post request to the https://httpbin.org/anything
endpoint, which returns the exact parameters sent. Here, which is what we use as our server.
Here, we must have seen the similarities between React and Hyperapp. For our purposes, I’ll describe Hyperapp as a lightweight alternative to React.
In the render function of the code above, we would notice the exact similarities to React. In fact, the only differences you would notice is the use of class
instead of React’s className
and onInput
in place of onChange
.
For the same reason we did not use
jsx
in the React form, is the same reason we have not usedjsx
here. If you use thenpm
package and prefer to usejsx
, please feel free.
Conclusion
In this tutorial, we have seen how easy it is to submit forms using 3 different JavaScript frameworks. We have also seen how to solve common issues when our forms are not displaying or not submitting as intended. Do you have any observations about this tutorials or views you want to share? Let us know in the comments.
Experience your Vue apps exactly how a user does
Debugging Vue.js applications can be difficult, especially when there are dozens, if not hundreds of mutations during a user session. If you’re interested in monitoring and tracking Vue mutations for all of your users in production, try LogRocket.
LogRocket is like a DVR for web and mobile apps, recording literally everything that happens in your Vue apps, including network requests, JavaScript errors, performance problems, and much more. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred.
The LogRocket Vuex plugin logs Vuex mutations to the LogRocket console, giving you context around what led to an error and what state the application was in when an issue occurred.
Modernize how you debug your Vue apps — start monitoring for free.
Get set up with LogRocket's modern React error tracking in minutes:
- Visit https://logrocket.com/signup/ to get an app ID
-
Install LogRocket via npm or script tag.
LogRocket.init()
must be called client-side, not server-side$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
// Add to your HTML: <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script> <script>window.LogRocket && window.LogRocket.init('app/id');</script>
- (Optional) Install plugins for deeper integrations with your stack:
- Redux middleware
- NgRx middleware
- Vuex plugin