util.dataforms
This module implements XEP-0004 data forms. Forms are a way to request and receive data from other XMPP entities. Sometimes this is automated, and sometimes the forms are rendered by clients and presented to a human.
Forms contain a list of fields. The core field types are defined in XEP-0004, with some special field types defined in later XEPs.
Usage
Define a form layout
Whether you will be receiving or sending data using forms (or both), the first step is to define your form’s “layout”, which describes all the fields in your form, and specifies their type.
local dataforms = require "util.dataforms";
local my_layout = {
-- Specify the form's title and instructions
title = "Request a Pony";
instructions = "To request a pony, fill out this form";
-- Now the fields are defined
-- It is conventional to start every form with a hidden field
-- called FORM_TYPE which lets anyone receiving the form know
-- what kind of form this is. The value should be a unique URI.
-- If they understand the form type, clients could render a special
-- UI, for example. You can read more about FORM_TYPE in XEP-0068.
{
type = "hidden";
name = "FORM_TYPE";
value = "xmpp:example.com/forms/pony_request";
};
{
type = "text-single"; -- The type of this field
name = "pony_name"; -- The unique internal name of this field
label = "Pony's name"; -- The label of this field (displayed to the user)
required = true; -- This is a mandatory field
};
{
type = "list-single";
name = "pony_breed";
options = {
"Shetland";
"Welsh";
"Connemara";
"Fjord";
"Other";
};
};
{
type = "boolean";
name = "pony_experience";
label = "Do you have prior experience with ponies?";
};
};
-- Now create a form object based on this layout
local myform = dataforms.new(my_layout);Sending forms
If a client wants to submit a form, it will typically request it first. Then the server will generate the form XML and send it to the client.
Use the :form() method to generate the form element
which is suitable for embedding in a stanza. The returned element will
be the <x xmlns='jabber:x:data'> element, containing
all your form’s fields.
-- If the client requests a form, we can generate the form XML to send them,
-- using the :form() method. In this example we're sending the form in a
-- message stanza, but most commonly the form is embedded in an iq response.
local some_stanza = st.stanza("message");
some_stanza:add_child(myform:form());Note: if you want to send a form where the fields
are already populated with data, you can provide that data to the
:form() method as a table. This example is just sending an
empty form to the client, so the client knows what the form fields
are.
Receiving form submissions
Next, the client will submit the completed form to you. You can use the form object to parse the form XML and turn it into a table of data.
-- Get the submitted form from the stanza
local submitted_form = some_stanza:get_child("x", "jabber:x:data");
-- Parse the form using the :data() method
local data, errors = my_form:data(submitted_form);
if not data then
-- Failed to parse the form!
-- 'errors' will be a map of [field_name] = error_string
for field_name, error_string in pairs(errors) do
module:log("warn", "Form error in field %s: %s", field_name, error_string);
end
return;
end
-- We have the submitted data
module:log("info", "Received request for pony %s", data.pony_name);Reference
new(layout)
Creates and returns a new form object using the given form layout. For a detailed description of the layout object, see Form layouts.
get_type(value)
Checks whether the provided value is a valid form element. If it is a
form, it returns the value of the FORM_TYPE field, or an
empty string. If it’s not, it returns nil plus an error
message.
This could be useful when you don’t know if a form was provided at
all, or if there are multiple forms (e.g. in XEP-0030) and you need to
pick out one in particular based on the FORM_TYPE.
form:form(data, type)
This method returns the form element
(<x xmlns='jabber:x:data'>) which can be embedded
into a stanza object (e.g using stanza:add_child()).
If data is not passed, the form fields will be empty or
use default values from the layout.
If data is passed, it must be a table where the keys are
the field names, and the values are appropriate values for each field
type. Any fields which are not included will be empty or the default
value will be used if one is specified in the layout.
The type parameter specifies the intention of the form.
Per XEP-0004, it should be one of "form",
"submit" or "result". If not specified, it
defaults to "form". This parameter should not be confused
with the unrelated FORM_TYPE field which is often included
in data forms!
form:data(form_element, current_values)
This method accepts a form element (e.g. the
<x xmlns='jabber:x:data'> element extracted from a
stanza), and parses and validates it according to the form’s layout. If
successful, it returns the data that was found in the form’s fields.
This data will be returned as a table, where each key is the field name,
and the value is the submitted value in a data type appropriate for that
field type.
If provided, current_values is a table of data that will
be used as a default if any fields specified in the layout are not
provided in the form. This allows partial form submissions where
existing data remains unchanged.
If form validation fails, the returned data will be nil.
The second result will be a table of errors, where the keys are field
names that failed to parse and the values are strings describing the
error.
Finally, the third result is always a table which contains as keys
all the field names that were present in the parsed form, and the value
true.
Form layouts
A form layout is a table, which can contain some key/value pairs, and also an array of fields.
Properties are:
title- The title of the form
instructions- Human-readable instructions related to the form
Fields
Each field is represented as a table.
Common field properties:
type- A string which specified the field types (known types are listed below).
name-
The field ‘name’ is usually an internal string such as
pony_nameand is used to refer to the field in data tables that are used as input/output of the form methods. var-
If specified, this overrides the field name in the form’s XML format
(the
nameis still used in data tables). If not specified, the fieldnameis used in the XML. label-
A human-readable string which names the field
(e.g.
Name of pony). desc- An optional human-readable description of the field.
datatype- Specify a field “subtype” used for validation. Valid types are specified in XEP-0122.
range_min- If appropriate for the data type, specifies a minimum acceptable value for this field. See XEP-0122 for details.
range_max- If appropriate for the data type, specifies a maximum acceptale value for this field. See XEP-0122 for details.
value- The value of the field. If specified in the layout, this is used as a default value when rendering the form.
options-
For list data types (
list-singleorlist-multi), this specifies an array of possible options in the list. Each entry in the list should be a string or a table of the form{ label = "Value label", value = "my_value" }.
Field types
Valid field types:
hidden- String, not presented to the user when rendering the form.
boolean- Boolean value, typically rendered as a checkbox.
- -
fixed - String, not editable by the user.
jid-single- String, must be a valid JID.
jid-multi- Array of strings, all entries must be valid JIDs.
text-single- String. Arbitrary single line of text.
text-multi- String, multi-line.
list-single- String. Allows selecting one item from a list of possible options.
list-multi- Array. Allows selecting zero or more items from a list of possible options.