Multi Level Dropdowns in NewForm.aspx / EditForm.aspx
Step 1: Create one Custom List where it holds all Multilevel data. (Backend
database for Multi Levels)
Step 2: Create the MainList Customlist with the following Columns
Level 1-> Single line of text
Level 2-> Single line of text
Level 3-> Single line of text
Step 3: Open Newform.aspx [MainList] in SharePoint Designer
i
– NewForm.aspx has to be customized so Close the existing
ListFormWebpart
Step 4: Include Customized form and include three dropdowns (level1,
level2,level2)
Ex: for Level1
<SharePoint:FormField runat="server" id="ff2{$Pos}" ControlMode="New" FieldName="Level_x0020_1"
__designer:bind="{ddwrt:DataBind(‘i’,concat(‘ff2′,$Pos),’Value’,’ValueChanged’,’ID’,ddwrt:EscapeDelims(string(@ID)),’@Level_x0020_1′)}"/>
<select id="Level1"></select>
Step 5:Create one javascript file[main.js] and include in newform.aspx
<script language="javascript" src="Main.js"></script>
Step 6: In Main.js Use Microsoft.XMLDom to access the sharePoint list as XML
Microsoft.XMLDOM will work only in IE. use XMLHttpRequest to make it work in
Firefox and Chrome
| xml_doc = new ActiveXObject("Microsoft.XMLDOM");
Step7: Create three different arrays and one object and collect all levels
value to respective array
var L1=new Array() var L2=new Array() var l3=new Array() var DataC=[]; xml_doc = new ActiveXObject("Microsoft.XMLDOM"); xml_doc.async = false; xml_doc.load("<server>/_vti_bin/owssvr.dll?Cmd=Display&List={ListID}&Query=*&XMLDATA=TRUE"); //STRVALUE = xml_doc.documentElement.childNodes(1).childNodes; STRVALUE = xml_doc.getElementsByTagName("z:row"); alert(STRVALUE.length) for(i=0;i<STRVALUE.length;i++) { L1[i]=STRVALUE[i].getAttribute("ows_Level1") L2[i]=STRVALUE[i].getAttribute("ows_Level2") L3[i]=STRVALUE[i].getAttribute("ows_Level3") } |
Step 8: Get unique values of first level value. Use the below javascript
function to get unique values for array
Array.prototype.unique = function() { var a = []; var l = this.length; for(var i=0; i<l; i++) { for(var j=i+1; j<l; j++) { // If this[i] is found later in the array if (this[i] === this[j]) j = ++i; } a.push(this[i]); } return a; }; |
Step 9: Get unique values for first level and populate the first dropdown
L1=L1.unique(); for(j=0;j<L1.length;j++) document.getElementById("Level1").options.add(new Option(L1[j],L1[j])) |
Step 10: Collate all level2 and level 3 data into objects
Ex: For Level 2 Data object DataC["ServerLevel2-Sample1"]
will hold all
level2 data for Serverlevel1-Sample1
Ex: For Level 3 Data object DataC["ServerLevel2-Sample1ServerLevel2-Sample11"]
will hold all level 3 data for the selection of Level1: Serverlevel1-Sample1 and
Level2 : ServerLevel2-Sample11
Step 11: Collecting level2 and level3 data into Object
for(SL1=0;SL1<L1.length;SL1++) { DataC[L1[SL1]]=[]; // Create object Ex: DataC["ServerLevel2-Sample1"] for(M=0;M<STRVALUE.length;M++) { if( STRVALUE[M].getAttribute("ows_Level1")==L1[SL1]) DataC[L1[SL1]].push(STRVALUE[M].getAttribute("ows_ServiceLevel2")) } DataC[L1[SL1]]=DataC[L1[SL1]].unique(); for(SL2=0;SL2<L2.length;SL2++) { DataC[L1[SL1]+L2[SL2]]=[]; for(M=0;M<STRVALUE.length;M++) if( STRVALUE[M].getAttribute("ows_Level1")==L1[SL1] && STRVALUE[M].getAttribute("ows_Level2")==L2[SL2]) DataC[L1[SL1]+L2[SL2]].push(STRVALUE[M].getAttribute("ows_Level3")) } } |
Step 12:
On Selecting level 1 , populating level 2 values in dropdown 2.
So initiate the onchange event for dropdown 1 and call a function LevelChange
<select id="Level1" onchange="LevelChange(‘Level2’,this.options[this.selectedIndex].text,this)"></select>
(LevelChange(TargetDropdown, Dropdown1value,this))
On Selecting level2 , populating level 3 values in dropdown 3
So initiate the onchange event for dropdown 2 and call a functio LevelChange
<select id="Level2" onchange="var t=document.getElementById(‘Level1’);LevelChange(‘Level3’,t.options[t.selectedIndex].text+this.options[this.selectedIndex].text,this)"></select>
(LevelChange(TargetDropdown, Dropdown1value+Dropdown2value,this))
On Selecting Level3 , No dropdown should populate
<select id="Level3" onchange="LevelChange(”,”,this)"></select>
(LevelChange(null, null,this))
Step 13: Create function levelChange
function LevelChange(ID,Data,this) { document.getElementById(ID).options.length=0; for(i=0;i<DataC[Data].length;i++) { document.getElementById(ID).options.add(new Option(DataC[Data][i],DataC[Data][i])) } } |
Step 14: Now on select each dropdown, the corresponding textbox should
populate the selected dropdown value.
So modifying the levelChange function a bit to pass the dropdown value to
textboxes. Grab the ID for each textbox from "ViewSource"
function LevelChange(ID,Data,Current) { if(Current.id!="Level3") { document.getElementById(ID).options.length=0; for(i=0;i<DataC[Data].length;i++) { document.getElementById(ID).options.add(new Option(DataC[Data][i],DataC[Data][i])) } } if(Current.id=="Level1") document.getElementById("ctl00_m_g_4ec47aa8_03c3_4083_b395_a581c10b60ba_ff2_1_ctl00_ctl00_TextField").value=Current.options[Current.selectedIndex].text if(Current.id=="Level2") document.getElementById("ctl00_m_g_4ec47aa8_03c3_4083_b395_a581c10b60ba_ff3_1_ctl00_ctl00_TextField").value=Current.options[Current.selectedIndex].text if(Current.id=="Level3") document.getElementById("ctl00_m_g_4ec47aa8_03c3_4083_b395_a581c10b60ba_ff4_1_ctl00_ctl00_TextField").value=Current.options[Current.selectedIndex].text } |
Step 15: Hide all three textboxes.
document.getElementById("ctl00_m_g_4ec47aa8_03c3_4083_b395_a581c10b60ba_ff2_1_ctl00_ctl00_TextField").style.display="none" document.getElementById("ctl00_m_g_4ec47aa8_03c3_4083_b395_a581c10b60ba_ff3_1_ctl00_ctl00_TextField").style.display="none" document.getElementById("ctl00_m_g_4ec47aa8_03c3_4083_b395_a581c10b60ba_ff4_1_ctl00_ctl00_TextField").style.display="none" |
Complete js file
Array.prototype.unique = function() { var a = []; var l = this.length; for(var i=0; i<l; i++) { for(var j=i+1; j<l; j++) { // If this[i] is found later in the array if (this[i] === this[j]) j = ++i; } a.push(this[i]); } return a; };
var L1=new Array() for(SL1=0;SL1<L1.length;SL1++)
function LevelChange(ID,Data,Current) } |
This is a great tutorial, I didn’t even think about using the owssrv.dll for this purpose. Great Job!
I modified LevelChange() a little to update child dropdown menu’s when a parent is modified:
function LevelChange(ID,Data,Current){
var undef;
if(Current.id!=”Level3″){
document.getElementById(ID).options.length=0;
if(null!=DataC[Data]){
for(i=0;i<DataC[Data].length;i++){
document.getElementById(ID).options.add(new
Option(DataC[Data][i],DataC[Data][i]))
$("#"+ID).val(DataC[Data][i])
}
tmp_text="";
tmp_next=parseInt(ID.substring(ID.length-1,ID.length))+1
tmp_item=tmp_next-1
tmp_next="Level"+tmp_next;
for(i=1;i<=tmp_item;i++){
to_get="Level"+i
tmp_text=tmp_text + document.getElementById(to_get).value
}
LevelChange(tmp_next,tmp_text,document.getElementById(ID))
}
}
if(Current.id=="Level1")…
if(Current.id=="Level2")…
if(Current.id=="Level3")…
}
I also added another function to check that the level dropdown equals the appropriate text field, and if it didn't to make the text field empty.
these two changes create the affect the text field *always* equals the dropdown so you can hide the original text fields with relative safety.
Happy Sharepointing!