Simulating AJAX calls
In Styleguide you can simulate AJAX calls so that you can test your client-side JavaScript that processes the server’s responses. The underlying concept in Styleguide’s implementation of AJAX is that you use a template to submit data in an AJAX session, and you populate another template with the server’s response.
The following example shows how to create a form for visitor comments, send the comment to the server, and then display the comment in the original web page.
Step 1: Create directory structure
All the files for your AJAX simulation are under the directory styleguide/
, preferably in their own subdirectory. Create the subdirectory in which you’ll create the Styleguide files, such as reader-comments/
.
theme-directory/ or express/
└── styleguide/
├── All.js
└── reader-comments/
├── ReaderResponse.hbs
├── ReaderResponse.json
├── ReaderSubmit.hbs
├── ReaderSubmit.js
└── ReaderSubmit.json
Referring to the previous illustration, the five files in the directory reader-comments/
are the minimum you need to simulate an AJAX session in Styleguide. You’ll create those files in the following steps.
Step 2: Create a template with a form
Simple AJAX deployments start with an HTML form. In the subdirectory you created for AJAX files (see illustration "AJAX directory structure"), create the template for the form used to submit a reader comment and display the AJAX response.
{{!-- Filename: ReaderSubmit.hbs --}}
<div class="ReaderSubmit">
<div class="CommentForm">
<form action="{{formActionUrl}}" method="{{method}}">
{{#element "body"}}
<div class="{{elementName}}">
<textarea name="{{this}}"></textarea>
</div>
{{/element}}
{{#element "submit"}}
<button class="{{elementName}}" type="submit">{{this}}</button>
{{/element}}
</form>
</div>
{{#with "comments"}}
<div class="CommentForm-comments">
{{~this~}}
</div>
{{/element}}
</div>
-
Declares the template name; this name appears in the corresponding data file.
-
Evaluates to a traditional HTML form with a
textarea
and a submit button. -
Evaluates to
<div class="ReaderSubmit-comments">
in which the AJAX response appears. The JavaScript function to display the response will query on the class name.
At load time, the reader submission form looks as follows.
Step 3: Create a data file for the form template
{
"_template": "ReaderSubmit.hbs",
"method": "post",
"formActionUrl": "ReaderResponse.html",
"body": "body",
"submit": "Submit",
"comments": "Comment appears here."
}
-
Associates this data file with the template you created in Step 1.
-
Specifies the template Styleguide populates with the server’s response. You’ll create this template in Step 4.
Step 4: Create template for response
You need to create a template that contains the server’s response to the AJAX input.
<div class="ReaderResponse">
{{#with "body"}}
<div class="ReaderResponse-body">
{{this}}
</div>
{{/with}}
</div>
-
Evaluates to
<div class="ReaderResponse-body">
. The JavaScript function places the AJAX response inside this div.
Step 5: Create data file for response template
Create a data file for the template you created in Step 4.
{
"_template": "ReaderResponse.hbs",
"_hidden": true,
"_wrapper": false,
"body": "Roses are read, violets are blue, most poems rhyme, but this one doesn't."
}
-
Associates this data file with the template you created in Step 4
-
Prevents the response template from appearing in the Styleguide UI—a typical practice for nested templates.
-
Indicates the returned template is not wrapped in any higher level templates—a typical practice for nested templates. For details about this key, see _wrapper.
-
Populates the response with static text.
Step 6: Create a JavaScript plugin file
Create a JavaScript file as a class that processes the event callbacks you want to capture as well as the response received from the server.
const COMMENTING_SELECTOR = '.ReaderSubmit'
const COMMENTING_COMMENTS_SELECTOR = COMMENTING_SELECTOR + '-comments'
const FormData = window.FormData
export default class ReaderSubmit {
constructor (element) {
this.element = element
this.bindEvents()
}
bindEvents () {
this.element.addEventListener('submit', (event) => this.onFormSubmit(event))
}
onFormSubmit (event) {
event.preventDefault()
const form = event.target
const formData = new FormData(form)
window.fetch(form.getAttribute('action'), {
method: 'POST',
body: formData
}).then((response) => {
if (response.status !== 200) {
throw new Error(response.statusText)
}
return response.text()
}).then((returnedComment) => {
document.querySelector(COMMENTING_COMMENTS_SELECTOR).innerHTML = returnedComment
}
).catch((error) => {
console.log(error)
})
}
}
-
Declares constant strings used in functions that access the DOM through class names, such as
document.querySelector
. Using constants in this manner is a best practice, as their values tie directly to the block names and element names in templates, and production-grade JavaScript files often reuse these names individually or in concatenation. -
Declares a class using the statement
export
. This statement is mandatory as it allows you to register the class as a plugin in Step 7. -
Class’s constructor. The constructor calls the function to bind events to the template’s controls.
-
Binds the event
submit
to the callbackonFormSubmit()
. -
Describes the callback
onFormSubmit()
using the standard AJAX construct window.fetch.
-
Sends the form data to the server and receive the subsequent response. In this example, the response is a static text “Roses are read, violets are blue, most poems rhyme, but this one doesn’t.”
-
Takes the received response (which is a string) and assign it to the div whose class name is
.ReaderSubmit-comments
. See the illustration "Result of AJAX session" for an example of the response’s appearance inside the originating web page.
Step 7: Register plugin
- In the theme’s
styleguide/
directory, create or open a fileAll.js
. (See the illustration "AJAX directory structure" for the location of this file.) - Add the following lines:
import plugins from '<path>/core/PluginRegistry.js' import ReaderSubmit from './reader-comments/ReaderSubmit.js' plugins.register(ReaderSubmit, '.ReaderSubmit')
-
Imports the Node.js plugin-registry package. This package comes with Styleguide, so you do not need to install it yourself.
-
Associates the class ReaderSubmit with the CSS class .ReaderSubmit. Any time the browser adds to the DOM an HTML element with the class .ReaderSubmit, it instantiates an object of class ReaderSubmit—the same class you created in the listing "JavaScript plugin file." For an illustration of the web page’s state after running the constructor, see the Template at load time example in Step 2 above.
-
Step 8: Run Styleguide
- Build and run your Styleguide project. From the
express/
or theme directory,gulp styleguide
. - In the browser, click Submit to observe the AJAX interaction.
Result of AJAX sessionReferring to the previous illustration, clicking Submit retrieves the text in the data file ReaderResponse.json
that you created in Step 5, and displays it in the div <div class="ReaderSubmit-comments">
.
See also:
- Getting Started (with AJAX)
- Using Fetch