Using HTML Forms in Schedules
Using Forms in Schedules
You can attach a form to a schedule using an HTML file. When the schedule is run, the values of the form's input elements (such as text boxes and select lists) are converted to JSON and attached to the Batch Variable, without overriding any other batch variables. You can then use the JSON macros in ReportMagic to read those values in your report.
To attach a form, open the Schedules page, create or edit a schedule, and use the Form HTML File chooser in the dialog to browse to and select your .html file.
Because a form has to be filled in by a person, forms can only be used with Run Now, not with scheduled (unattended) runs.
About the HTML file
- The HTML file may contain any standard HTML, including CSS and scripts
- The HTML file must contain exactly one
<form></form>element - The HTML file must be valid
- Every input you want to capture must have a
nameattribute, otherwise it is ignored - Multi-select inputs (drop-downs that allow more than one selection) must include the
multipleattribute - In the report variables these are represented as a JArray (in normal mode) or a semi-colon separated string (in legacy mode)
- All button elements are automatically disabled, except buttons whose type is
submitorreset - You do not need to add a submit button; ReportMagic adds one if your form does not already have one
An Example Form
A form can be as simple or as rich as you like. This example uses a little CSS to lay the form out, groups related inputs with fieldsets, and includes a small script with a function that ties a "Select all" checkbox to a multi-select list. Save it as a .html file and choose it in the Form HTML File chooser.
<style>
.rm-form { max-width: 520px; font-family: "Segoe UI", Arial, sans-serif; }
.rm-form fieldset { border: 1px solid #cbd5e1; border-radius: 8px; margin-bottom: 12px; padding: 12px; }
.rm-form legend { font-weight: 600; padding: 0 6px; }
.rm-form label { display: block; margin: 6px 0 2px; }
.rm-form input[type="text"], .rm-form select { width: 100%; padding: 6px; }
</style>
<form class="rm-form">
<fieldset>
<legend>Report</legend>
<label for="reportTitle">Report title</label>
<input type="text" id="reportTitle" name="reportTitle" value="Monthly Summary">
<label for="outputFormat">Output format</label>
<select id="outputFormat" name="outputFormat">
<option value="pdf" selected>PDF</option>
<option value="docx">Word</option>
<option value="xlsx">Excel</option>
</select>
</fieldset>
<fieldset>
<legend>Sections to include</legend>
<label><input type="checkbox" id="allSections" onchange="toggleAllSections(this)"> Select all</label>
<select id="sections" name="sections" multiple size="4">
<option value="alerts">Alerts</option>
<option value="devices">Devices</option>
<option value="uptime">Uptime</option>
<option value="traffic">Traffic</option>
</select>
</fieldset>
<fieldset>
<legend>Delivery</legend>
<label for="emailTo">Email recipient</label>
<input type="text" id="emailTo" name="emailTo" value="reports@example.com">
</fieldset>
</form>
<script>
function toggleAllSections(checkbox) {
var options = document.getElementById("sections").options;
for (var i = 0; i < options.length; i++) {
options[i].selected = checkbox.checked;
}
}
</script>
Using Form Variables in your Report
Each named input becomes a variable you can reference with standard macros. For the single-value inputs above, use the variable name in braces:
[String:value={reportTitle}]
[String:value={outputFormat}]
[String:value={emailTo}]
You can use any macro that accepts a text variable.
The multi-select input named sections holds every value the user selected. In legacy mode it is a semi-colon separated string, so the standard List macros apply. In normal mode (when Force normal mode is set on the schedule) it is a JArray, and you can manipulate it with the JArray macros. The variable is named after the select element's name attribute.
// Get all selected sections as a list
[Json.List: jArray=`{=sections}`, jsonPath="$.[*]", storeAs=AllSections]
// Count how many sections were selected
[Array.Count:value=`{sections}`]
// Iterate over each selected section and print its value
[ForEach:values={sections}, storeAs=Section]
[String:value={Section}]
[EndForEach:]
Loading Cached Values into a Form
A form can load data that a report has already calculated and stored as a cached value (see Cache.Set and Cache.Get), and make it available to the form's own JavaScript. This lets a form be driven by real data instead of hard-coded lists.
To use a cached value, add a placeholder element carrying a data-rm-cached-value attribute set to the cache key:
- When the form is rendered, ReportMagic resolves the value on the server and provides it to your form as an ordinary JavaScript variable of the same name, for example
myKey(orwindow["myKey"]if the key is not a valid variable name) - The value keeps its stored type: numbers arrive as numbers, true/false as booleans, and JObject or JArray values as JavaScript objects and arrays, ready to use without any conversion
- A schedule may read a cached value that is either scoped to that schedule, or a single value shared across the Tenant - exactly the same access rule that applies when the schedule itself reads the cache
- If the schedule cannot access the referenced value, a short failure message is shown in place of the placeholder and the value is not exposed to the form
- Names reserved by the browser (such as
locationordocument) cannot be used and will show the failure message instead - On success the placeholder element is left empty (the data goes to JavaScript), so you do not need to hide it
Here is the full picture. First, earlier in the report, the customer's list of sites is calculated into a variable. For this example we build the list directly with the Calculate macro shorthand (in practice it would usually come from a query or an earlier macro):
[=:`list('London', 'Manchester', 'Glasgow')`, =>sites]
That stores the list in a variable named sites. The report then caches it so it is available to forms. Because the value is supplied by late evaluation - the {=sites} syntax passes the actual list rather than text - the cached value keeps its type automatically as a JArray, so no type parameter is needed:
[Cache.Set: key=customerSites, value={=sites}, scope=Global, expires=2027-01-01]
Then the Run form for that schedule declares the cached value and builds a drop-down from it, so the list of sites is always current without being hard-coded into the form:
<div data-rm-cached-value="customerSites"></div>
<label for="site">Site</label>
<select id="site" name="site"></select>
<script>
// customerSites is provided by ReportMagic as an ordinary JavaScript array.
// A script placed after the element it updates does not need any special wrapper.
if (typeof customerSites !== "undefined") {
var select = document.getElementById("site");
customerSites.forEach(function (siteName) {
var option = document.createElement("option");
option.value = siteName;
option.textContent = siteName;
select.appendChild(option);
});
}
</script>
When the user runs the schedule they see a Site drop-down populated from the cached data. The chosen value is submitted as the site form variable, ready to use in the report just like any other form variable.
Auto-populated Connection Pickers
Every Report Library report needs a Connection to run against. Instead of asking the user to type the exact name, a form can add a <select> that ReportMagic fills in automatically with the Tenant's Connections of a chosen type.
To use it, add a data-rm-connections-value attribute to a <select>, set to the Connection type you want - usually the Connection Type name with "Connection" appended, for example MerakiConnection. Check the Connections list in the admin app if you are not sure.
- ReportMagic fills the select with a prompt option plus one option per matching Connection
- If the Tenant has no Connections of that type, the select is disabled and a short message is shown instead
- Only Connection names are ever sent to the browser - never a URL, username or password
Most Tenants have one obvious Connection they always want to use for a given type of report. A Tenant Admin can set this as a default in the admin app under ReportMagic > Macro Defaults: create an entry for the Connection macro of that type (for example [Meraki.Connection:]) with Parameter Name set to name and Value set to the Connection's exact name.
- Once set, the picker opens with that Connection already selected - the user can still change it
- Each Connection type has its own separate default
- If there is no default, or it no longer matches an existing Connection, the picker opens unselected exactly as before
Here is an example, based on the picker used by the Meraki Wireless Health report:
<form> <label for="connection">Connection</label> <select id="connection" name="connection" data-rm-connections-value="MerakiConnection" required></select> </form>
The required attribute alone is enough to stop the report being run until a Connection is chosen - no extra script needed, and you do not need to add your own submit button either.
When the user opens the form, the Connection drop-down is already filled in with the Tenant's Meraki Connections, with the default one pre-selected if the Tenant has one.