Custom customer form 
The gadget spec URL could not be found


In this section, we will be implementing a one-many custom form to maintain customer and customer address details. The form that we will be implementing using the "HTML Forms" perspective is the same as the customer form that we implemented using the "Forms" perspective.

The customer form consists of the following:

  • Input form elements for customer id, email, first name, last name, phone, sex and date of birth.
  • Label form element for age.
  • Input form elements for customer address details.
  • Buttons to save and delete the customer details, add and delete customer address details.
HTML form specification for the custom customer form includes:
  • Model Level APIs
    • getRoot() which returns the root of the graph(instance), and its wrapper methods getValue(cellName) that returns the value of the cell, getDisplayValue(cellName,Format) that returns the display value of the cell in the format specified and getList(referenceCellName, ChildModelName) that returns the list of child objects.
  • View definitions using JSTL
    • Input form elements for customer id, email, first name, last name, phone, sex and date of birth.
    • Action elements to perform workflow submit and delete the current instance.
  • Controller methods
    • update
    • invoke
    • showList
    • remove

Here's the code to create the custom form to maintain customer details described above.



<style>
.h22{height:22px;}
.w40{width:40px;min-width:40px;}
.w60{width:60px;min-width:60px;}
.w75{width:75px;min-width:75px;}
.w100{width:100px;min-width:100px;}
.w120{width:120px;min-width:120px;}
.w150{width:150px;min-width:150px;}
.w200{width:200px;min-width:200px;}
</style>

<div>
<div class="Form_Title">Customer Details</div>
   <br>

<table cellpadding=0 cellspacing=0  style='border-collapse:collapse'>

      <tr>
         <td class='h22 w100 vmiddle hleft Form_Elements'>
         Customer ID
         </td>

         <td class='h22 w200 vmiddle hleft'>
         <input type="text" class="h22 vmiddle hleft textbox Form_Elements" name="CustomerID"  value="${getRoot().getDisplayValue('CustomerID','Text','Text')}" data-id='${getRoot().getValue("SheetId")}' data-format='Text' onchange='${id}.update(this)'/>
         </td>

         <td class='h22 w100 Form_Elements'>
         </td>

         <td class='h22 w100 hleft Form_Elements'>
         Email
         </td>

         <td class='h22 w200'>
         <input type="text" class="h22 vmiddle hleft textbox Form_Elements" name="Email" value='${getRoot().getValue("Email")}' data-id='${getRoot().getValue("SheetId")}' onchange='${id}.update(this)'/>
         </td>
      </tr>

      <tr>
         <td class='h22 w100 vmiddle hleft Form_Elements'>
         First Name
         </td>

         <td class='h22 w200 vmiddle hleft'>
         <input type="text" class="h22 vmiddle hleft textbox Form_Elements" name="FirstName" value="${getRoot().getValue("FirstName")}" data-id='${getRoot().getValue("SheetId")}' data-format='Text' onchange='${id}.update(this)'/>
         </td>

         <td class='h22 w100 Form_Elements'>
         </td>

         <td class='h22 w100 hleft Form_Elements'>
         Phone
         </td>

         <td class='h22 w200'>
         <input type="text" class="h22 vmiddle hleft textbox Form_Elements" name="Phone" value="${getRoot().getValue("Phone")}" data-id='${getRoot().getValue("SheetId")}' onchange='${id}.update(this)'/>
         </td>
      </tr>

      <tr>
         <td class='h22 w100 vmiddle hleft Form_Elements'>
         Last Name
         </td>

         <td class='h22 w200 vmiddle hleft'>
         <input type="text" class="h22 vmiddle hleft textbox Form_Elements" name="LastName" value="${getRoot().getValue("LastName")}" data-id='${getRoot().getValue("SheetId")}' data-format='Text' onchange='${id}.update(this)'/>
         </td>

         <td class='h22 w100 Form_Elements'>
         </td>

         <td class='h22 w100 hleft Form_Elements'>
         Date of Birth
         </td>

         <td class='h22 w200'>
         <input type="date" class="h22 textbox calendar" name="DOB" value="${getRoot().getDisplayValue('DOB','MM/dd/yyyy','Date')}" data-id='${getRoot().getValue("SheetId")}' data-type='date' data-format='MM/dd/yyyy' data-send='true' onchange='${id}.update(this)'/>
         </td>
      </tr>

      <tr>
         <td class='h22 w100 vmiddle hleft Form_Elements'>
         Sex
         </td>

         <td class='h22 w200 vmiddle hleft'>
         <input type="Text" class="h22 vmiddle hleft combobox Form_Elements" name="Sex" value="${getRoot().getValue("Sex")}" data-id='${getRoot().getValue("SheetId")}' data-staticlist="[{'label':'None','idval':''},{'label':'Female','idval':'Female'},{'label':'Male','idval':'Male'}]" onclick='${id}.showList(this)'/>
         </td>

         <td class='h22 w100 Form_Elements'>
         </td>

         <td class='h22 w100 hleft Form_Elements'>
         Age
         </td>

         <td class='h22 w200'>
         <label class="h22 w200 vmiddle hleft Form_Elements" name="Age" value="${getRoot().getValue('Age')}" data-format='Text' data-id='${getRoot().getValue("SheetId")}' data-format='Text'>${getRoot().getValue('Age')}</label>
         </td>
      </tr>

   </table>
</div>

<br>

<div>

<input type='button' id='Workflow_Save' name='Workflow' value='Save' class='h22 w60 button' data-id='${getRoot().getValue("SheetId")}' data-send='true'  data-status='Category details saved successfully!' data-target='Worktop' data-validate='true' onclick = "${id}.invoke(this)"/>

<input type='button' value='Delete' class='h22 w60 button' data-id='${getRoot().getValue("SheetId")}' data-send='true'  data-status='Customer details deleted successfully!' data-target='Worktop' data-validate='true' onclick='${id}.remove(this)'/>

</div>

We have already seen how we have to specify the OrangeScape view specification for the input textbox elements and the action element for workflow submit. In the customer form, we have additionally used the static dropdown list for sex and calendar widget for the date of birth input element. The additional specifications include:

Input element: 

  • data-staticlist: This parameter can be used to specify the static list values for the combobox. 

<input type="Text" class="h22 vmiddle hleft combobox Form_Elements" name="Sex" value="${getRoot().getValue("Sex")}" data-id='${getRoot().getValue("SheetId")}' data-staticlist="[{'label':'Female','idval':'Female'},{'label':'Male','idval':'Male'}]" onclick='${id}.showList(this)'/>

  • getDisplayValue(cellName,Format) method has been used to format the display value for date of birth parameter that is of date datatype.

<input type="date" class="h22 textbox calendar" name="DOB" value="${getRoot().getDisplayValue('DOB','MM/dd/yyyy')}" data-id='${getRoot().getValue("SheetId")}' data-type='date' data-format='MM/dd/yyyy' data-send='true' onchange='${id}.update(this)'/>


Now that we have added the form elements for maintaining the customer details, let's get started with the required form elements for maintaining customer address details. Firstly, we will add a button to create a new instance in the "CustomerAddress" model. 

Required specifications for the action element to create a new child instance: 
  • data-path: This parameter must be used to specify the path to access the child model where a new instance is to be created. The format for specifying the data path is "/referenceCellName/childModelname"
  • "onclick" event has been used to invoke the "create" controller method to add a new child model instance.

<input type='button' value='Add' class='h22 w40 button NormalFormCell'  data-path="/CustomerID/CustomerAddress" data-send='true' onclick='${id}.create(this)'/><br>


Required specifications for the action element to delete an existing child instance: 
    • data-path: This parameter must be used to specify the path to access the child model where a new instance is to be created. The format for specifying the data path is "/referenceCellName/childModelname/SheetId" where SheetId is the SheetId of the child instance to be deleted.
    • "onclick" event has been used to invoke the "remove" controller method to delete the child model instance.

    <a href='javascript:void(0);' id='Delete' data-id='${instance.getValue("SheetId")}' data-path="/CustomerID/CustomerAddress/${instance.getValue('SheetId')}" data-send='true'  onclick="${id}.remove(this)"><img class='image NormalFormCell' src='/runtime/images/delete.png'/></a>



    Here's the code to maintain customer address details.


    <table cellpadding=0 cellspacing=0  style='border-collapse:collapse'>
       <tr>
          <td class='h22 w200 Form_Title'>
          Customer Address
          </td>

          <td class='h22 w40'>
          <input type='button' value='Add' class='h22 w40 button NormalFormCell'  data-path="/CustomerID/CustomerAddress" data-send='true' onclick='${id}.create(this)'/><br>
          </td>
       </tr>
    </table>


    <br>

    <table cellpadding=0 cellspacing=0  style='border-collapse:collapse'>
       <tr class="List_Heading">

          <td class='h22 w40 vmiddle hcenter List_Heading Form_Elements'>
          Default
          </td>

          <td class='h22 w100 hcenter List_Heading Form_Elements'>
          Address Type
          </td>

          <td class='h22 w120 vmiddle List_Heading hcenter Form_Elements'>
          Address Line #1
          </td>

          <td class='h22 w120 vmiddle hcenter List_Heading Form_Elements'>
          Address Line #2
          </td>

          <td class='h22 w120 vmiddle hcenter List_Heading Form_Elements'>
          Address Line #3
          </td>

          <td class='h22 w100 vmiddle hcenter List_Heading Form_Elements'>
          City
          </td>

          <td class='h22 w75 vmiddle hcenter List_Heading Form_Elements'>
          State
          </td>

          <td class='h22 w75 vmiddle hcenter List_Heading Form_Elements'>
          Country
          </td>

          <td class='h22 w75 vmiddle hcenter List_Heading Form_Elements'>
          Zip Code
          </td>

          <td class='h22 w75 vmiddle hcenter List_Heading Form_Elements'>
          Actions
          </td>
       </tr> 

       {for instance in getRoot().getList('CustomerID','CustomerAddress','CreatedAt',false)}

       <tr>
          <td class='h22 w40 vmiddle hcenter Form_Elements'>
          <input type="checkbox" class="h22 vmiddle hleft checkbox" name="Default" value="${instance.getValue('Default')}" data-id='${instance.getValue("SheetId")}' data-staticlist="[{'label':'True','idval':1.0},{'label':'False','idval':0.0}]" onchange='${id}.update(this, {'Default': parseValue(this.checked)})'/>
          </td>

          <td class='h22 w100 hcenter Form_Elements'>
          <input type='text' name='AddressType' class='combobox Form_Elements' data-id='${instance.getValue("SheetId")}' data-format='Text' value="${instance.getValue('AddressType')}"  data-staticlist="[{'label':'None','idval':''},{'label':'Billing','idval':'Billing'},{'label':'Delivery','idval':'Delivery'}]" onclick='${id}.showList(this)'/>
          </td>

          <td class='h22 w120 vmiddle hcenter Form_Elements'>
          <input type="text" class="h22 vmiddle hleft textbox Form_Elements" name="AddressLine1" value="${instance.getValue('AddressLine1')}" data-id='${getRoot().getValue("AddressLine1")}' data-format='Text' onchange='${id}.update(this)'/>
          </td>

          <td class='h22 w120 vmiddle hcenter Form_Elements'>
          <input type="text" class="h22 vmiddle hleft textbox Form_Elements" name="AddressLine2" value="${instance.getValue('AddressLine2')}" data-id='${getRoot().getValue("AddressLine2")}' data-format='Text' onchange='${id}.update(this)'/>      
          </td>

          <td class='h22 w120 vmiddle hcenter Form_Elements'>
          <input type="text" class="h22 vmiddle hleft textbox Form_Elements" name="AddressLine3" value="${instance.getValue('AddressLine3')}" data-id='${getRoot().getValue("AddressLine3")}' data-format='Text' onchange='${id}.update(this)'/>
          </td>

          <td class='h22 w100 vmiddle hcenter Form_Elements'>
          <input type="text" class="h22 vmiddle hleft textbox Form_Elements" name="City" value="${instance.getValue('City')}" data-id='${getRoot().getValue("City")}' data-format='Text' onchange='${id}.update(this)'/>
          </td>

          <td class='h22 w75 vmiddle hcenter Form_Elements'>
          <input type="text" class="h22 vmiddle hleft textbox Form_Elements" name="State" value="${instance.getValue('State')}" data-id='${getRoot().getValue("State")}' data-format='Text' onchange='${id}.update(this)'/>
          </td>

          <td class='h22 w75 vmiddle hcenter Form_Elements'>
          <input type="text" class="h22 vmiddle hleft textbox Form_Elements" name="Country" value="${instance.getValue('Country')}" data-id='${getRoot().getValue("Country")}' data-format='Text' onchange='${id}.update(this)'/>
          </td>

          <td class='h22 w75 vmiddle hcenter Form_Elements'>
          <input type="text" class="h22 vmiddle hleft textbox Form_Elements" name="ZipCode" value="${instance.getValue('ZipCode')}" data-id='${getRoot().getValue("ZipCode")}' data-format='Text' onchange='${id}.update(this)'/>
          </td>

          <td class='h22 w75 vmiddle hcenter Form_Elements'>
          <a href='javascript:void(0);' id='Delete' data-id='${instance.getValue("SheetId")}' data-path="/CustomerID/CustomerAddress/${instance.getValue('SheetId')}" data-send='true'  onclick="${id}.remove(this)"><img class='image NormalFormCell' src='/runtime/images/delete.png'/></a>
          </td>
       </tr>

       {/for}

    </table>


    Boundary must be defined for this form because this form processes the data from the current model (Customer) and its child model (CustomerAddress). To define the boundary for this form, open the customer form and click on the "Boundary" tab at the bottom of the HTML forms perspective. "CustomerAddress" model has a one-many relationship with the customer model. Click on the "One-Many" icon and select the checkbox for "CustomerAddress(CustomerID)".


    You can use the preview option to validate the customer form design. The customer form will be displayed as shown in the screen capture.


    ċ
    Boobesh Ramalingam,
    Oct 11, 2011, 9:11 PM