This page provides a detailed, walk-through tutorial that describes how you might go about building your first Alpaca form. It isn't all that complicated but this guide goes step-by-step. Because, well... some people are all about step-by-step instructions with lots of details.
If you're more interested in seeing a quick demo, check out our examples page.
Launch your favorite text editor and create an empty HTML file. We're going to build a web page so you're
going to want to make sure the HTML file has a head
section and a body
section.
In the head
section, make sure that you include jQuery and also Alpaca.
In the body, we'll add a single DIV
element. We'll use this to hold our form.
It might end up looking something like this:
<html> <head> <!-- jquery --> <script type="text/javascript" src="//code.jquery.com/jquery-1.11.1.min.js"></script> <!-- bootstrap --> <link type="text/css" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" /> <script type="text/javascript" src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script> <!-- handlebars --> <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.js"></script> <!-- alpaca --> <link type="text/css" href="//cdn.jsdelivr.net/npm/alpaca@1.5.27/dist/alpaca/bootstrap/alpaca.min.css" rel="stylesheet" /> <script type="text/javascript" src="//cdn.jsdelivr.net/npm/alpaca@1.5.27/dist/alpaca/bootstrap/alpaca.min.js"></script> </head> <body> <div id="form"></div> </body> </html>
So far so good. Of course, the page doesn't do much yet. Let's add in a form!
Add a div
to the body section of your HTML file. This DIV
is a placeholder element
that we're going to use to hold our Alpaca form. We use jQuery to get a hold of the DIV
and then we call the $.alpaca
function on it to make things happen.
When we call this function, we can pass in the JSON schema of the form as well as optional configuration options that tell Alpaca what kinds of controls to render as well as how to lay them out.
Let's start by specifying only the schema
parameter. This is a JSON schema document that describes
the data structure of a "User Feedback" object with three properties, name, feedback and ranking.
As illustrated in the following example, Alpaca is able to render a basic feedback form based on the provided schema. It maps object property to form field based on it data type and format. For example, a string type object property will be mapped to a text field. However if we specify a list of allowed values for the property with an enum attribute, Alpaca will instead render a radio button group (or a drop-down select if the number of enum options is more than three) with all values listed in the enum attribute. Since it is not a required field, Alpaca will automatically append a None option to the radio button group which maps to empty value.
The feedback form we have at this point is very basic because the schema parameter only describes the data structure and format. As for the options of the rendered form fields, Alpaca makes a lot of assumptions, e.g. the size of text field is set as 40 as default.
<html> <head> <link type="text/css" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" /> <link type="text/css" href="//cdn.jsdelivr.net/npm/alpaca@1.5.27/dist/alpaca/bootstrap/alpaca.min.css" rel="stylesheet" /> <script type="text/javascript" src="//code.jquery.com/jquery-1.11.1.min.js"></script> <script type="text/javascript" src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script> <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.js"></script> <script type="text/javascript" src="//cdn.jsdelivr.net/npm/alpaca@1.5.27/dist/alpaca/bootstrap/alpaca.min.js"></script> </head> <body> <div id="form"></div> <script type="text/javascript"> $(document).ready(function() { $("#form").alpaca({ "schema": { "title":"User Feedback", "description":"What do you think about Alpaca?", "type":"object", "properties": { "name": { "type":"string", "title":"Name" }, "feedback": { "type":"string", "title":"Feedback" }, "ranking": { "type":"string", "title":"Ranking", "enum":['excellent','ok','so so'] } } } }); }); </script> </body> </html>
If you load this page in a browser, you'll then see the following:
To render a better feedback form, let us add an options parameter in addition to the schema parameter. The options parameter is another JSON document that specifies type and options for the rendered form fields. It now sets the size of name field as 20, maps the feedback object property to a textarea field and uses drop-down select for the ranking object property with custom option labels.
The options parameter can also be used to provide additional field labels and help messages or overwrite the ones that came from the schema parameter. In general, we can couple the same schema parameter with different options parameters to render the form in various formats.
<html> <head> <link type="text/css" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" /> <link type="text/css" href="//cdn.jsdelivr.net/npm/alpaca@1.5.27/dist/alpaca/bootstrap/alpaca.min.css" rel="stylesheet" /> <script type="text/javascript" src="//code.jquery.com/jquery-1.11.1.min.js"></script> <script type="text/javascript" src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script> <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.js"></script> <script type="text/javascript" src="//cdn.jsdelivr.net/npm/alpaca@1.5.27/dist/alpaca/bootstrap/alpaca.min.js"></script> </head> <body> <div id="form"></div> <script type="text/javascript"> $(document).ready(function() { $("#form").alpaca({ "schema": { "title":"User Feedback", "description":"What do you think about Alpaca?", "type":"object", "properties": { "name": { "type":"string", "title":"Name" }, "feedback": { "type":"string", "title":"Feedback" }, "ranking": { "type":"string", "title":"Ranking", "enum":['excellent','ok','so so'] } } }, "options": { "helper": "Tell us what you think about Alpaca!", "fields": { "name": { "size": 20, "helper": "Please enter your name.", "placeholder": "Enter your name" }, "feedback" : { "type": "textarea", "rows": 5, "cols": 40, "helper": "Please enter your feedback." }, "ranking": { "type": "select", "helper": "Select your ranking.", "optionLabels": ["Awesome!", "It's Ok", "Hmm..."] } } } }); }); </script> </body> </html>
If you reload your browser, you'll now see something like this:
The ultimate reason for using Alpaca forms service is to provide end users with a friendly interface for collecting their inputs. Those collected information normally needs to be submitted to and stored in a backend system such as database, CMS etc.
With the schema parameter and the optional options parameter, Alpaca has rendered a decent feedback form with normal HTML form tags. To make it interact with backend services, we have a few options:
Alpaca sets the name attribute of a rendered field based on its schema property name in case we didn't specify it through the options parameter. For the following example, we will have "name" for the name field and "your_feedback" for the feedback field.
We have also provide Alpaca with a new data parameter which is a JSON document used by Alpaca as the initial data for populating the form. We have also make both name and ranking field as required field. Now if you leave the name field empty, Alpaca will automatically invalidate the field and display an error message.
You may also notice this rendered form has different styles than the previous example. That is because we set Alpaca with a view parameter which makes Alpaca to pick a different set of templates for form rendition.
<html> <head> <link type="text/css" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" /> <link type="text/css" href="//cdn.jsdelivr.net/npm/alpaca@1.5.27/dist/alpaca/bootstrap/alpaca.min.css" rel="stylesheet" /> <script type="text/javascript" src="//code.jquery.com/jquery-1.11.1.min.js"></script> <script type="text/javascript" src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script> <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.js"></script> <script type="text/javascript" src="//cdn.jsdelivr.net/npm/alpaca@1.5.27/dist/alpaca/bootstrap/alpaca.min.js"></script> </head> <body> <div id="form"></div> <script type="text/javascript"> $(document).ready(function() { $("#form").alpaca({ "data": { "name": "Diego Maradona", "feedback": "Very impressive.", "ranking": "excellent" }, "schema": { "title":"User Feedback", "description":"What do you think about Alpaca?", "type":"object", "properties": { "name": { "type":"string", "title":"Name", "required":true }, "feedback": { "type":"string", "title":"Feedback" }, "ranking": { "type":"string", "title":"Ranking", "enum":['excellent','ok','so so'], "required":true } } }, "options": { "form":{ "attributes":{ "action":"http://httpbin.org/post", "method":"post" }, "buttons":{ "submit":{} } }, "helper": "Tell us what you think about Alpaca!", "fields": { "name": { "size": 20, "helper": "Please enter your name." }, "feedback" : { "type": "textarea", "name": "your_feedback", "rows": 5, "cols": 40, "helper": "Please enter your feedback." }, "ranking": { "type": "select", "helper": "Select your ranking.", "optionLabels": ["Awesome!", "It's Ok", "Hmm..."] } } }, "view" : "bootstrap-edit" }); }); </script> </body> </html>
If you reload your browser, you'll now see something like this:
Alpaca is capable of not only rendering a form based on JSON schema but also reassembling form inputs into a JSON document according to the data structure described by the same JSON schema.
This brings us a better option for interacting Alpaca with backend services. As shown in the following example,
we can specify a click handler for any of our form buttons. The handler has a this
set to the
form instance which we can use to call getValue
as well manually run validation, check validation
state and execute any other form methods we'd like. The form instance exposes a method called
submit
to post the form as well as a method called ajaxSubmit
that will submit
behind the scenes and hand back a jQuery promise object.
We also can use a postRender
callback to get a hold of the rendered form object once it has been
drawn to the screen. We can use this to hook in additional event listeners, change CSS or bind other parts
of the DOM to our form for interactivity.
For developers, this will be the place to do any required post-processing since Alpaca will feed the callback
function with the top-most form control that it constructs. We can easily gain access to any other Alpaca form
control by using API such as
renderedForm.children
, renderedForm.childrenByPropertyId
,
renderedForm.getControlByPath
, etc. From any Alpaca form control, we can get the DOM element
of its outer DOM element calling field.getFieldEl().
<html> <head> <link type="text/css" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" /> <link type="text/css" href="//cdn.jsdelivr.net/npm/alpaca@1.5.27/dist/alpaca/bootstrap/alpaca.min.css" rel="stylesheet" /> <script type="text/javascript" src="//code.jquery.com/jquery-1.11.1.min.js"></script> <script type="text/javascript" src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script> <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.js"></script> <script type="text/javascript" src="//cdn.jsdelivr.net/npm/alpaca@1.5.27/dist/alpaca/bootstrap/alpaca.min.js"></script> </head> <body> <div id="form"></div> <script type="text/javascript"> $(document).ready(function() { $("#form").alpaca({ "data": { "name": "Diego Maradona", "feedback": "Very impressive.", "ranking": "excellent" }, "schema": { "title":"User Feedback", "description":"What do you think about Alpaca?", "type":"object", "properties": { "name": { "type":"string", "title":"Name", "required":true }, "feedback": { "type":"string", "title":"Feedback" }, "ranking": { "type":"string", "title":"Ranking", "enum":['excellent','ok','so so'], "required":true } } }, "options": { "form":{ "attributes":{ "action":"http://httpbin.org/post", "method":"post" }, "buttons":{ "submit":{ "title": "Send Form Data", "click": function() { var val = this.getValue(); if (this.isValid(true)) { alert("Valid value: " + JSON.stringify(val, null, " ")); this.ajaxSubmit().done(function() { alert("Posted!"); }); } else { alert("Invalid value: " + JSON.stringify(val, null, " ")); } } } } }, "helper": "Tell us what you think about Alpaca!", "fields": { "name": { "size": 20, "helper": "Please enter your name." }, "feedback" : { "type": "textarea", "name": "your_feedback", "rows": 5, "cols": 40, "helper": "Please enter your feedback." }, "ranking": { "type": "select", "helper": "Select your ranking.", "optionLabels": ["Awesome!", "It's Ok", "Hmm..."] } } }, "postRender": function(control) { control.childrenByPropertyId["name"].getFieldEl().css("background-color", "lightgreen"); } }); }); </script> </body> </html>
If you reload your browser, you'll now see something like this:
Alpaca is a client-side forms engine which means form rendition and data processing all happen on client side e.g. client browser. This provides a great foundation for high performance and scalability since JSON is the native data format that all browsers understand and it is the easiest format for data manipulation. Once the jQuery and Alpaca library are downloaded and cached on client side, there will be no other overhead.
Plugging Alpaca into your existing application should be fairly straightforward. All you need to do is to provide an endpoint for serving Alpaca with data in JSON and another endpoint for taking re-assembled JSON document with user inputs from Alpaca for data persistence. Most modern day backend systems may already have those two endpoints.
As illustrated by the above examples, using Alpaca is mainly through configuration rather than coding. Since schema and options parameters are also JSON documents, they can be stored in and served by your back systems as well. If you can plugin an adapter that converts XML document to JSON document, you can use Alpaca for your XML data as well.