12 January 2008

Dynamic Picklist, load values from a XML file



There are some dynamicpicklist examples on the Internet. You may find it from CRM SDK as well, and there's A (slightly) different approach to dynamic picklists from Greg Owens.

But none of those can meet my client's requirement. We have 2 picklists(which is normal), but picklist2 has hundreds of items. And those picklists repeat 3 times on all activites. Furthermore, they don't want to use another entity. So I create a XML file to keep the data, and using it dynamicly fill out picklist2 when picklist1 has value selected. It works great, and you only need to maintain one XML file.

This is a very simple XML to do the demonstration, put it ('section.xml') into the root folder of CRMWeb. The idea is: when user selects type1 in picklist1, then picklist2 only shows item1, item2, item3; when user selects type2 in picklist1,the picklist2 only shows item4, item5, item6.


<?xml version="1.0" encoding="utf-8" ?>
<Section>
<type1>
<item>item1</item>
<item>item2</item>
<item>item3</item>
</type1>
<type2>
<item>item4</item>
<item>item5</item>
<item>item6</item>
</type2>
</Section>


Suppose there are two picklists on crmForm, picklist2's value depends on picklist1's selection.
In my example:
picklist1 is: new_type1, it has two values: 'typeA/typeB' and 'typeC/typeD'
picklist2 is: new_section1, it doesn't have any value, and I add another nvarchar attribute: new_section1Text to save it's value(see example)



/*
Form.onLoad() event
GetItems() is a global function to get section's list items based on type's selection
typeValue: picklist1's DataValue
section: picklist2(object)
sectionText: picklist2.SelectedText
*/

GetItems = function(typeValue, section, sectionText)
{
//clean the section object
section.length = 0;

//it is the index of picklist2.SelectedText in XML file
var sectionTextIndex = 0;

//get the typeName, used for XML node
var typeName = 0;

switch(typeValue)
{
case "1" : typeName = "type1"; break;
case "2" : typeName = "type2"; break;
case "0" : return;
}

//load XML file
var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = false;
xmlDoc.load("/section.xml");

//get all items under this type
xmlDoc = xmlDoc.getElementsByTagName(typeName)[0];
var items = xmlDoc.getElementsByTagName('item');

//insert all items into section object
for(var i=0; i<items.length; i++)
{
section.AddOption(items(i).firstChild.nodeValue, i+1);
if((sectionText != null)&&(sectionText.DataValue == items(i).firstChild.nodeValue))
{
sectionTextIndex = i+1;
}
}

return sectionTextIndex;
}

GetPicklist(crmForm.all.new_type1, crmForm.all.new_section1, crmForm.all.new_section1text);

function GetPicklist(type, section, sectionText)
{
if(sectionText.DataValue != null)
{
//select the right one
section.DataValue = GetItems(type.DataValue, section, sectionText);
}
}

/*
Form.onSave() event, save the current new_section1's selectedText
Becasue we need to add this option to new_section1 on Form.onLoad()
*/

SetPicklist(crmForm.all.new_section1 , crmForm.all.new_section1text);

function SetPicklist(section, sectionText)
{
if(section.SelectedText != "")
{
sectionText.DataValue = section.SelectedText;
section.length = 0;
}
}

/*
new_type1.onChange() event to call GetItem() funciton, passing new_type1.DataValue and new_section1, sectionText as parameters
*/
if(crmForm.all.new_type1.DataValue != null)
{
GetItems(crmForm.all.new_type1.DataValue, crmForm.all.new_section1, null);
}
else
{
crmForm.all.new_section1.options.length = 0;
}

12 comments:

Anonymous said...

Jim,

This is a brilliant script. It is exactly what I was looking for. I was testing your script out and I ran into a Error message. Every time I tried to Save, I get an error message that says "One or more of the option values for this picklist are not in the range of allowed values." Am I doing something wrong? Did you run into this problem as well? I am currently using CRM 4.0. Any help will be grealy appreciated. And again great script.

Jim Wang said...

Thanks for that, you are right. It looks like .Net 2/3 has been improved :)

You only need to add the below code to onSave() event:

section.length = 0;

I will update my post.
Cheers,
Jim

Anonymous said...

Hi, I really need to apply this method in my project, it's very useful for me. But i have some issues:
1- I'm getting a javascript error once i choose TypeA/typeb or tupeC/typeD. It's on the onchange even: 'null' is null or not an object. I guess it's happening because of the parameter null, how to fix it?
2-i placed the XML file in the wwwroot folder under Microsoft CRM. is it fine?
3- You said to add section.length=0; below onSave(). Where exactly should it be added?
It's urgent!
Thanks in advance

Unknown said...

Hello,

I have this code in my onSave() form event but when i try to save an activity the following message appears:

"One or more of the option values for this picklist are not in the range of allowed values"

Can you help me, please?

Thanks.


//onSave() code

SetPicklist(crmForm.all.new_area , crmForm.all.new_categoriaText);

function SetPicklist(section, sectionText)
{
if(section.SelectedText != "")
{
sectionText.DataValue = section.SelectedText;
section.length = 0;
}
}

Ricardo Sánchez said...

Hello Jim,
I would like to know if there is any idea about a third dynamic picklist in this code, for example, region, county and city.
Thanks in advance

Anonymous said...

Jim, Is there a way to have a picklist value populate based on the owner of the record?

Jim Wang said...

Doug, yes. You may need to get the user's security role(is it what you want?) first then filter the result.

Anonymous said...

酒店經紀PRETTY GIRL 台北酒店經紀人 ,禮服店 酒店兼差PRETTY GIRL酒店公關 酒店小姐 彩色爆米花酒店兼職,酒店工作 彩色爆米花酒店經紀, 酒店上班,酒店工作 PRETTY GIRL酒店喝酒酒店上班 彩色爆米花台北酒店酒店小姐 PRETTY GIRL酒店上班酒店打工PRETTY GIRL酒店打工酒店經紀 彩色爆米花

Tudorian said...

Hi,

Nice post very helpful. In my project there is a strange thing happening. After my dynamic list are populated their size changes. I have to manually re-size the windows so that they are aligned as original. Do you know what may be the cause?

Thanks

Jalal Hussain said...

Hi Jim,
This is a good script. i was testing ur script its working fine but when i am reopen this case then i am getting an error: automation server can't create object.

Unknown said...

Jim, thanks for this script.

I have a picklist populated dinamically in CRM 2011 using addOption() function. Everything works ok, but when i try to get the selected option of the picklist (On the onChange event, using getSelectedOption().text), i got null value.

Any idea?

Thanks in advance

Quân Đào said...

học kế toán thực hành cấp tốc
học kế toán thực hành cấp tốc
học kế toán thực hành tại cầu giấy
học kế toán thực hành tại thanh xuân
]học kế toán thực hành tại hà đông
học kế toán thực hành tại long biên
học kế toán thực hành tại long biên
học kế toán thực hành tại hải phòng
học kế toán thực hành tại bắc ninh
học kế toán thực hành tại tphcm
học kế toán thực hành tại quận 3
học kế toán thực hành tại hải phòng
học kế toán thực hành tại bắc ninh
học kế toán thực hành tại bình dương
học kế toán thực hành tại biên hòa
học kế toán thực hành tại vinh
học kế toán thực hành tại vinh
học kế toán thực hành tại huế
học kế toán thực hành tại đà nẵng
học kế toán thực hành tại đà nẵng
học kế toán thực hành tại đà nẵng
học kế toán thực hành tại hải dương
học kế toán thực hành tại hưng yên
học chứng chỉ kế toán
học kế toán ở đâu tốt