Step 1: Create Request Form

2024-03-28

In this step, you will create the user interface for collecting requests. A wiki containing JavaScript can be designed to accept user input and translate it into the information needed in the database. In this example, users specify the desired reagent, a desired quantity, and some user contact information, submitting requests with a form like the following:

Folders and Permissions

First create a separate folder where your target users have "insert" permissions. Creating a separate folder allows you to grant these expanded permissions only for the folder needed and not to any sensitive information. Further, insertion of data into the lists can then be carefully controlled and granted only through admin-designed forms.

  • Log in to your server and navigate to your "Tutorials" project. Create it if necessary.
    • If you don't already have a server to work on where you can create projects, start here.
    • If you don't know how to create projects and folders, review this topic.
  • Create a new subfolder named "Reagent Request Tutorial." Accept the default "collaboration" folder type.
    • On the User/Permissions page, click Finish and Configure Permissions.
    • Uncheck Inherit permissions from parent.
    • Next to Submitter, add the group "Site: All Site Users".
    • Remove "Guest" from the Reader role if present.
    • Click Save and Finish.

You will now be on the home page of your new "Reagent Request Tutorial" folder.

Import Lists

Our example reagent request application uses two lists. One records the available reagents, the other records the incoming requests. Below you import the lists in one pass, using a "list archive". (We've pre-populated these lists to simulate a system in active use.)

  • Click to download this list archive: ReagentTutorial.lists.zip
  • Go to (Admin) > Manage Lists.
  • Click Import List Archive.
  • Click Browse or Choose File and select the list archive you just downloaded.
  • Click Import List Archive.

You will see the two lists now available.

Create the Request Page

Requests submitted via this page will be inserted into the Reagent Requests list.

  • Click the folder name link ( Reagent Request Tutorial) to return to the main folder page.
  • In the Wiki web part, click Create a new wiki page.
  • Give it the name "reagentRequest" and the title "Reagent Request Form".
  • Click the Source tab.
  • Scroll down to the Code section of this page.
  • Copy and paste the HTML/JavaScript code block into the Source tab.
  • Click Save & Close.
  • To make a more convenient dashboard for users/requesters: enter Page Admin Mode and remove the Subfolders web part.

The page reagentRequest now displays the submission form, as shown at the top of this page.

See a live example.

Notes on the source code

The following example code uses LABKEY.Query.selectRows and LABKEY.Query.insertRows to handle traffic with the server. For example code that uses Ext components, see LABKEY.ext.Store.

View the source code in your application, or view similar source in the interactive example. Search for the items in orange text to observe any or all of the following:

  • Initialization. The init() function pre-populates the web form with several pieces of information about the user.
  • User Info. User information is provided by LABKEY.Security.currentUser API. Note that the user is allowed to edit some of the user information obtained through this API (their email address and name), but not their ID.
  • Dropdown. The dropdown options are extracted from the Reagent list. The LABKEY.Query.selectRows API is used to populate the dropdown with the contents of the Reagents list.
  • Data Submission. To insert requests into the Reagent Requests list, we use LABKEY.Query.insertRows. The form is validated before being submitted.
  • Asynchronous APIs. The success in LABKEY.Query.insertRows is used to move the user on to the next page only after all data has been submitted. The success function executes only after rows have been successfully inserted, which helps you deal with the asynchronous processing of HTTP requests.
  • Default onFailure function. In most cases, it is not necessary to explicitly include an onFailure function for APIs such as LABKEY.Query.insertRows. A default failure function is provided automatically; create one yourself if you wish a particular mode of failure other than the simple, default notification message.

Confirmation page dependency. Note that this source code requires that a page named "confirmation" exists before you can actually submit a request. Continue to the next step: Step 2: Confirmation Page to create this page.

Code

<div style="float: right;">    <input value='View Source' type='button' onclick='gotoSource()'><br/><br/>    <input value='Edit Source' type='button' onclick='editSource()'> </div>

<form name="ReagentReqForm">    <table cellspacing="0" cellpadding="5" border="0">        <tr>            <td colspan="2">Please use the form below to order a reagent.                All starred fields are required.</td>        </tr> <tr><td colspan="2"><br/></td></tr>        <tr>            <td colspan="2"><div id="errorTxt" style="display:none;color:red"></div></td>        </tr>        <tr>            <td valign="top" width="100"><strong>Name:*</strong></td>            <td valign="top"><input type="text" name="DisplayName" size="30"></td>        </tr> <tr><td colspan="2" style="line-height:.6em"><br/></td></tr>        <tr>            <td valign="top" width="100"><strong>Email:*</strong></td>            <td valign="top"><input type="text" name="Email" size="30"></td>        </tr> <tr><td colspan="2" style="line-height:.6em"><br/></td></tr>        <tr>            <td valign="top" width="100"><strong>UserID:*</strong></td>            <td valign="top"><input type="text" name="UserID" readonly="readonly" size="30"></td>        </tr> <tr><td colspan="2" style="line-height:.6em"><br/></td></tr>        <tr>            <td valign="top" width="100"><strong>Reagent:*</strong></td>            <td valign="top">                <div>                    <select id="Reagent" name="Reagent">                        <option>Loading...</option>                    </select>                </div>            </td>        </tr> <tr><td colspan="2" style="line-height:.6em"><br/></td></tr>        <tr>            <td valign="top" width="100"><strong>Quantity:*</strong></td>            <td valign="top"><select id="Quantity" name="Quantity">                <option value="1">1</option>                <option value="2">2</option>                <option value="3">3</option>                <option value="4">4</option>                <option value="5">5</option>                <option value="6">6</option>                <option value="7">7</option>                <option value="8">8</option>                <option value="9">9</option>                <option value="10">10</option>            </select></td>        </tr> <tr><td colspan="2" style="line-height:.6em"><br/></td></tr>        <tr>            <td valign="top" width="100"><strong>Comments:</strong></td>            <td valign="top"><textarea cols="53" rows="5" name="Comments"></textarea></td>        </tr> <tr><td colspan="2" style="line-height:.6em"><br/></td></tr>

<tr>            <td valign="top" colspan="2">                <div align="center">                    <input value='Submit' type='button' onclick='submitRequest()'>            </td>        </tr>    </table> </form> <script type="text/javascript">

window.onload = init();

// Navigation functions. Demonstrates simple uses for LABKEY.ActionURL.    function gotoSource() { window.location = LABKEY.ActionURL.buildURL("wiki", "source", LABKEY.ActionURL.getContainer(), {name: 'reagentRequest'});    }

function editSource() { window.location = LABKEY.ActionURL.buildURL("wiki", "edit", LABKEY.ActionURL.getContainer(), {name: 'reagentRequest'});    }

// Initialize the form by populating the Reagent drop-down list and    // entering data associated with the current user.    function init() {        LABKEY.Query.selectRows({            schemaName: 'lists',            queryName: 'Reagents',            success: populateReagents        });

document.getElementById("Reagent").selectedIndex = 0;

// Set the form values        var reagentForm = document.getElementsByName("ReagentReqForm")[0];        reagentForm.DisplayName.value = LABKEY.Security.currentUser.displayName;        reagentForm.Email.value = LABKEY.Security.currentUser.email;        reagentForm.UserID.value = LABKEY.Security.currentUser.id;    }

// Populate the Reagent drop-down menu with the results of    // the call to LABKEY.Query.selectRows.    function populateReagents(data) {        var el = document.getElementById("Reagent");        el.options[0].text = "<Select Reagent>";        for (var i = 0; i < data.rows.length; i++) {            var opt = document.createElement("option");            opt.text = data.rows[i].Reagent;            opt.value = data.rows[i].Reagent;            el.options[el.options.length] = opt;        }    }

// Enter form data into the reagent request list after validating data    // and determining the current date.    function submitRequest() {        // Make sure the form contains valid data        if (!checkForm()) {            return;        }

// Insert form data into the list.        LABKEY.Query.insertRows({            schemaName: 'lists',            queryName: 'Reagent Requests',            rowDataArray: [{                "Name": document.ReagentReqForm.DisplayName.value,                "Email": document.ReagentReqForm.Email.value,                "UserID": document.ReagentReqForm.UserID.value,                "Reagent": document.ReagentReqForm.Reagent.value,                "Quantity": parseInt(document.ReagentReqForm.Quantity.value),                "Date": new Date(),                "Comments": document.ReagentReqForm.Comments.value,                "Fulfilled": 'false'            }],            success: function(data) {                // The set of URL parameters.                var params = {                    "name": 'confirmation', // The destination wiki page. The name of this parameter is not arbitrary.                    "userid": LABKEY.Security.currentUser.id // The name of this parameter is arbitrary.                };

// This changes the page after building the URL. Note that the wiki page destination name is set in params.                var wikiURL = LABKEY.ActionURL.buildURL("wiki", "page", LABKEY.ActionURL.getContainer(), params);                window.location = wikiURL;            }        });    }

// Check to make sure that the form contains valid data. If not,    // display an error message above the form listing the fields that need to be populated.    function checkForm() {        var result = true;        var ob = document.ReagentReqForm.DisplayName;        var err = document.getElementById("errorTxt");        err.innerHTML = '';        if (ob.value == '') {            err.innerHTML += "Name is required.";            result = false;        }        ob = document.ReagentReqForm.Email;        if (ob.value == '') {            if(err.innerHTML != '')                err.innerHTML += "<br>";            err.innerHTML += "Email is required.";            result = false;        }        ob = document.ReagentReqForm.Reagent;        if (ob.value == '') {            if(err.innerHTML != '<Select Reagent>')                err.innerHTML += "<br>";            err.innerHTML += "Reagent is required.";            result = false;        }        if(!result)            document.getElementById("errorTxt").style.display = "block";        return result;    }

</script>

Start Over | Next Step (2 of 4)