ItemType List

100% of people found this useful
ItemType List

Filed under: [Edit Tags]

An alternative to using Innovator Lists that supports a dynamic Add capability.

 

Requirements:

1. Automatically inserts an <Add> selection for designated for Selection Lists, unless the Form is not opened for update.  The Selection LIsts do not have to be pre-populated with the <Add> selection.

2. If the user selects <Add> then a pop-up window will be displayed that allows the user to enter a new text/value combination for the Selection List.  This pop-up window is the same one that appears if the user had the privilege to add a record to the list via /Administrator/Lists.  Thus, the new entry is reflected in the List on the Form and in the Innovator database.

3. After the user adds a new text/value combination then it will be automatically selected in the forms Selection List

4. When a Form is displayed/re-displayed then the Selection Lists will automatically be re-populated with the latest values from the database.  This over-comes the biggest problem with Innovator "out-of-the-box" lists, they are not dynamically repopulated (ie. In Innovator 9.0.1 if the list contains 3 text/value pairs when user A logs on the Innovator and displays a form that uses the list, then the Administrator adds a 4th text/value pair in another Innovator session, even if user A refreshes the form display they will not see the 4th text/value pair unless they log off Innovator and log back on).

 

Solution:

1.  I did not utilize the Innovator List itemtype to store my lists, instead I created my own itemtypes.  For example, I created a "lbrand" itemtype and included the following 2 fields (which are similar to the properties in an Innovator List itemtype):

llabel String 25 characters Required, Unique (there is no requirement to always make this 25 characters)


lvalue String  1 character  Required, Unique (there is no requirement to always make this 1 character, e.g. you could have 2 character values.  Also you are not required to have a lvalue property if your list is just a list of labels)

I included llabel in the keyed_name for the lbrand itemtype.  So this defines a specific list.

2.  I created a Form for the lbrand itemtype so that I could pre-populate it with labels/values.
examples:
label     value
Ford      F
Pontiac   P
Chrysler  C

3.  I included lbrand as a property on any itemtypes where it was required (e.g. the Part itemtype).  Generally, I defined this property to match the corresponding lvalue property so that the lvalue would be stored.  I have also used it to store the ID of the record from the list.

4.  To include this lbrand as a selection list on a form (e.g. the Part form), I defined an html field type on the form and gave it the name lbrand.  I defined the html field as follows:

<select name="lbrand" size="1"  style="font-weight: bold"  itemlist="1" itemtype="lbrand" itemadd="1"
onpropertychange="if (event.propertyName=='selectedIndex' && this.selectedIndex!=-1) if (window.handleItemChange) handleItemChange('lbrand',this.options(this.selectedIndex).value)">
</select>

Note that I included 3 attributes in this Select that are non-standard:

itemlist="1" is there so that my code can find all of these special Select objects on the Form
itemtype='lbrand" is there so that my code can determine which SQL table to find the label/values for this Select
itemadd="1" is there so that my code can determine if this Select should support the <Add> capability

Note the onpropertychange procedure.  The key bit of code is "handleItemChange('lbrand',this.options(this.selectedIndex).value)".  This
is an Innovator built-in method that will take the value of the selected row from the list and use it to update the lbrand property (e.g.
in the Part table).

5.  I wrote a Method called, LoadList, and include it as an "OnFormPopulated" Form event (e.g. in the Part form definition).  Disclaimer:
I have removed some Customer-specific code that I can not share, it is possible that this code may not compile if I made a mistake doing this.

// name:LoadList.js
//   purpose: Initialize all <select> elements that are to be populated from
//            item data.  These are used instead of the standard Innovator List controls
//            that are populated from Innovator lists.  These <select> elements have:
//            1. a custom attribute named "itemlist" set to "1". [required]
//            2. a custom attribute named "itemtype" set to the itemtype that contains the list values. [required]
//            3. a custom attribute named "itemwhere" set to a SQL where clause appropriate for the itemtype. Used to filter the list [optional]
//            4. a custom attribute named "itemadd" set to "1" if an "<Add>" entry is to be appended to the beginning of the list values. [optional]
//            5. a custom attribute named "itemvalue" set to "1" if Item values are to be displayed instead of the normal Item labels.  [optional]
//
//   created: 11/19/2008
//
//  ====================================================================================================

var innovator  = document.thisItem.newInnovator();  // thisItem is the part item that will be created
var loadListCache;  // Global variable used in lLoadListAdd and lLoadListCache functions

function lLoadListAdd(){
//   purpose: Called as a field onChange event by item data <select>'s.  This function implements the code to support
//            the <Add> functionality for the pull down list.
// ======================================================================================================

 var innovator  = document.thisItem.newInnovator();  // thisItem is the part item that will be created
 // Note, "this" is not an Innovator Item, rather is it the HTML Select object from the form
 var lval = this.value;  // This captures the value selected from the list
 var lname = this.itemtype;  // This captures the name of the associated item
 if (lval == '<Add>') {
  
  var newItemNd = top.aras.uiNewItemEx(lname);
  var newItemId = newItemNd.getAttribute("id");
 
  
  do {
   var waitRet = confirm("Please add the new list entry.  Save, unlock and close it, then return to this dialog box and click OK ");
   if (waitRet === false){
    top.aras.uiCloseWindowEx(newItemId);
    top.aras.removeFromCache(newItemNd);
    this.value = loadListCache; // Reset back to previous selection
    return;
   }
   
   newItemNd = innovator.getItemById(lname,newItemId);
   if(newItemNd){
    var newPC = newItemNd.getProperty("keyed_name");
    var newPV = newItemNd.getProperty("lvalue");
    if (newPV === undefined){newPV = newPC;}  //some Lists do not have the lvalue property
   }
  } while (!newItemNd);

  var listControl = this;
  var oOption = document.createElement("OPTION");
  oOption.text = newPC;
  if (listControl.itemvalue == "1"){oOption.text = newPV;}
  oOption.value = newPV;
  oOption.selected = true;
  listControl.add(oOption);
 }
 else if (lval == '<-Select->') {  // See comments below concerning <-Select->
  alert("You can not pick <-Select->, make another selection");
  this.value = loadListCache; // Reset back to previous selection
 }
}  //End of function lLoadListAdd() definition

function lLoadListCache() {
//   purpose: Called as a field onclick event by item data <select>'s.  This function implements the code to support
//            resetting selection back to previous selection.
// ======================================================================================================

 loadListCache = this.value;
}  //End of function lLoadListCache() definition

// Start of main procedure
// Loop through the "select" elements
var elements = document.getElementsByTagName("select");
for (var i=0; i<elements.length; i++){
 // Look for a custom attribute named "itemlist"
 if (elements[i].itemlist == "1") {
  var listControl = elements[i];
  
  // If control has already been loaded then just enable/disable it as appropriate
  if (listControl.length > 0) {
   if (!document.isEditMode) {listControl.disabled = true;}
   else {
    listControl.disabled = false;
    // Here you could add Application-specfic code to disable controls
    
    // listControl.disabled = true;
   }
   continue;
  }

                // The next 2 statements register these procudures as onchange/onclick evenets
  
  listControl.onchange = lLoadListAdd;
  listControl.onclick = lLoadListCache;
  
  // If itemadd flag is set then create an <Add> option
  if (elements[i].itemadd == "1") {
   var oOption2 = document.createElement("OPTION");
   oOption2.text = "<-Select->";  //<-Select-> is needed if the visible length of the control = 1
                                                       //This is due to an Internet Explorer bug that pre-selects the first
                                                       //option in a list if the visible length = 1.
   oOption2.value = oOption2.text;
   listControl.add(oOption2);
   var oOption = document.createElement("OPTION");
   oOption.text = "<Add>";
   oOption.value = oOption.text;
   listControl.add(oOption);
  }

  if (!document.isEditMode) {listControl.disabled = true;}
  else {
   // Here you could add Application-specfic code to disable controls
    
    // listControl.disabled = true;
   
  }

  // Now retrieve the entries to be added as options to the select
  var pcListItem = innovator.newItem(listControl.itemtype,'get');
  pcListItem.setAttribute('select','keyed_name,lvalue');
  pcListItem.setAttribute('orderBy','keyed_name');
  if (listControl.itemvalue == "1"){pcListItem.setAttribute('orderBy','lvalue');}
  if (listControl.itemwhere){pcListItem.setAttribute('where',listControl.itemwhere);}
  var pcListItems = pcListItem.apply();
  
  var pcListCount = pcListItems.getItemCount;
  if (pcListCount > 0) {
   for (var j=0; j<=pcListCount-1; j++) {
    oOption = document.createElement("OPTION");
    oOption.text = pcListItems.getItemByIndex(j).getProperty('keyed_name');
    if (listControl.itemvalue == "1"){oOption.text = pcListItems.getItemByIndex(j).getProperty('lvalue');}
    oOption.value = pcListItems.getItemByIndex(j).getProperty('lvalue');
    // Some item lists will not have a "value" field, in addition to "keyed_name"
    if (oOption.value == "undefined"){oOption.value = oOption.text;}
    // If thisItem has a value=Option.text, then set this Option=selected
    var strItemType = listControl.itemtype;
    if (listControl.name == "lparent") {
     var recordValue = document.thisItem.getProperty("lparent");
    }
    else {
     recordValue = document.thisItem.getProperty(strItemType);
    }
    listControl.add(oOption);
    if ((recordValue != "undefined") & (recordValue == oOption.value)){
     oOption.selected = true;
    }
   }
  }
 }
}


// Loop through the "input" elements on the Form that have itemlist = "1", they will always be readonly

elements = document.getElementsByTagName("input");
for (i=0; i<elements.length; i++){
 // Look for a custom attribute named "itemlist"
 if (elements[i].itemlist == "1") {
  var inputControl = elements[i];
  var searchTable = inputControl.itemtype;
  var searchValue = document.thisItem.getProperty(searchTable);

  // Now retrieve the entry to be display in the <input> element
  var ipListItem = innovator.newItem(searchTable,'get');
  ipListItem.setAttribute('select','keyed_name,lvalue');
  ipListItem.setAttribute('where',searchTable + ".lvalue = '" + searchValue + "'" );
  var ipListItems = ipListItem.apply();
  
  var ipListCount = ipListItems.getItemCount;
  if (ipListCount == 1) {    
    inputControl.value = ipListItems.getItemByIndex(0).getProperty('keyed_name');   
  }
  // Otherwise just replace with value from thisItem
  else {inputControl.value = searchValue;}
 }
}

 

Issues:

If the user selects <Add> from the list, the form that is displayed for the user to add a new list entry is initially displayed "mimimized".  I have yet to determine how to fix this.

Recent Comments

Leave the first comment for this page.