The CRM Grid – A Microsoft CRM Blog

Greg Owens’ rose-tinted MS-CRM mumblings

A (slightly) different approach to dynamic picklists

The MS CRM client-side SDK has an example for filtering dynamic picklist values – an example in widespread use (Ronald has a post on this too). I found this example wasn’t flexible enough for handling situations where the list of picklist options might grow in the future, since it relies on “related” options being consecutive in the list. It also meant that an option can only apply to one “group”

This query has also just been raised by Naaz in the Microsoft Forums.

Here is the solution I used. I find it much more flexible than the SDK example, it just required a bit more coding!

Overview:
Basically I define an array for each of the “groups”. I then add the integer values of those picklist options which are permissible for each group, to the appropriate array. When the “group field” is changed I then use a case statement to apply the correct array of options to the picklist.

In my example, I will filter a list of foods (new_food), based on the food category (new_foodcategory).

Categories will be called:

  • Vegetarian
  • Italian
  • PrePackaged

Please note:
I’ve not had a chance to run this, it’s just trimmed from my live code with example data. Also this code does not deal with resetting of the “food” field, if the food category changes so you will need to account for this.

The Code:

// ************************************************************************
// ** Purpose:
// **
// ** Only show foods permitted by the food category field
// **
// ************************************************************************
//set references to our fields
var oFoodCategory = crmForm.all.new_foodcategory;
var oFood = crmForm.all.new_food;

// keep a copy of the original options and reset the picklist before we start firking about
if(!oFood.originalPicklistValues)
{
oFood.originalPicklistValues = oFood.Options;
}
else
{
oFood.Options = oFood.originalPicklistValues;
}

// create an array to hold the required picklist values for each category
var oArrayVegetarian = new Array();
var oArrayItalian = new Array();
var oArrayPrePackaged = new Array();

// text values correspond to the picklist values in the 'food' field
// I keep this updated if I can as it is useful when reviewing the code!
//1 Cabbage
//2 Pasta
//3 Bread
//4 Parma Ham
//5 Apple
//6 Mushy Peas
//7 Chewing Gum
//8 Chocolate
//9 Zucchini
//10 Plum tomatoes
//11 Ciabbata
//12 Salami

// *** This is the bit you would edit to add/remove options to your lists *** //
	oArrayVegetarian.push(1,2,3,5,6,7,8,9,10,11);
	oArrayItalian.push(2,4,9,10,11,12);
	oArrayPrePackaged.push(2,4,6,7,8);
// *** No more editing *** //

// Now call the appropriate filtering parameters
// the values in each "case" clause refer to the text in the category dropdown
if(oFoodCategory.DataValue != null)
{
	switch(oFoodCategory.SelectedText)
	{
		case 'Vegetarian':
		filterPicklist(oArrayVegetarian);
		break;

		case 'Italian':
		filterPicklist(oArrayItalian);
		break;

		case 'PrePackaged':
		filterPicklist(oArrayPrePackaged);
		break;
	}
}

function filterPicklist(oDesiredOptions)
{

	var oTempArray = new Array();

	// loop through all items in the master list
	for (var i=oFood.length-1;i >= 0;i--)
	{
	
	// if the option value is in the list of desired values for this foodgroup
	// then add the option to our temp array and remove the
	// item from the desired option array
		for (j=oDesiredOptions.length;j >= 0;j--)
		{
			if(oFood[i].value == oDesiredOptions[j])
			{
				oTempArray[i] = true;
				oDesiredOptions.splice(j,1);
			}
		}
	}

	// Now remove all options from the master list that were not marked as required
	for (var i=oFood.length;i >= 0;i--)
	{
		if(oTempArray[i] != true)
		{
			oFood.remove(i)
		}
	}
}

Advertisements

15 Comments»

  Cornel wrote @

Hi Greg,

congrats… u have a nice blog here… what do u say about a link exchange? I already added ur blog in my list (“the blogs I read”). check out mine if u got the time… and if u find it useful u may add it to ur list too.
Thanks,
Cornel

P.S. Keep up the good work!

  Naaz wrote @

I am unable to track the error. its saying oColour[i].value is null or not an object. can you please help.

  Greg Owens wrote @

Hi Naaz

The style used in the blog isn’t great at displaying code it seems (I need to look at it and make some changes). I think the problem is possibly that some code is not displayed properly here, for example line 86:
for (var i=oColour.length;i >= 0;i–)

Should end with minus, minus, close bracket “-” “-” “)” but it only displays as a single “minus”. Check the code – each of the three For… loops should end with two minus signs.

Let me know how you get on. In the meantime I’ll try and sort this rubbish CSS style!

  Mark wrote @

Hello,

I am trying to implement this code and am getting an error stating that there is an invalid character. Did you ever get around to testing this code? I think this is sheer genius, but I am missing something here. Any help would be great!

Thanks!

  Greg Owens wrote @

Hey Mark. Actually I never did đŸ˜¦ Thanks for the kick up the bum, I’ll see if I can take a few minutes tomorrow and get it to work properly!

I need to sort out the rubbish example too – colours?! lol!

I think there’s an option for me to attach a text file to these posts so that might be safer.

Thanks greatly for your feedback – hope to have this working properly tomorrow đŸ™‚

  Greg Owens wrote @

OK – that’s the formatting sorted. I can’t test the content at this hour so will update more tomorrow!

  Ian Hurst wrote @

Greg,

Great article, very useful.

Think there are a few errors in the example code that could do with editing for other users:

1. In the switch statement and the if expression just before the variable ‘oColour’ should be ‘oColourCategory’:

if(oColourCategory.DataValue != null)
{
switch(oColourCategory.SelectedText)
{

2. I also believe that in the function ‘filterPicklist’ there is an off by one error in each of the for loops. Each of the start parameters for the for loop should be ‘length – 1’ instead of ‘length’.

Once again thanks for article really useful, just trying to ensure others can easily use.

  Greg Owens wrote @

Thanks Ian and crikey there were more than “a few errors” in that code of mine. New Year’s resolution is to not post anything until I actually test it…!! In case you think you’re going mad, I shuld mention I’ve changed the example from “colours” to foodgroups as it seems much more coherent!

Thanks to all that have commented so far and sincere apologies to anyone who has wasted time trying to correct my errors…

  Mark wrote @

Greg,

Thanks for the update to your blog. I haven’t had time to test out the new code, but I did figure it out later that day. (Sorry for the late post, I was on vacation). If you don’t mind, I posted my changes to your initial code on my blog and credited you (of course).

http://austincrm.blogspot.com/2007/12/non-sequential-dynamic-picklist.html

Thanks for the awesome ideas!

Mark

  Geron Profet wrote @

Hello Greg,

Thanks for your ideas on how to filter picklists. I have taken this approach one step further to make it completely dynamic. The idea is that the values of the second picklist start with the values of the first picklist. This way users can change the items without having to change the javascript.

http://crmxpg.nl/wp/?p=549

Thanks again for the original idea.

Cheers,
Geron

  Steve Shaw wrote @

Thanks for the code you guys, has anyone tried populating a picklist from values in a related entity?

[…] 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. […]

  Oliver wrote @

Hi, fantastic post. This is probably a stupid question, but I’m curious – I tried a modified version of this (I just need to hide old obsolete picklist items, not based on a criteria) but I’m not sure how insert the first null option on the picklist – when the form is opened, the picklist has a “default” value of the first object in the array, as opposed to a blank value.

  Greg Owens wrote @

Hi Oliver

As you’ve suggested, such “default” picklist values have no value or text:

<OPTION title="" selected value=""></OPTION>

The code above would need to be modified to handle that special case, for example, by notionally considering this default option as having a “value” of 0, then adding an extra clause in the FilterPicklist function. This is untested, but code should look something like this:

Set up your “desired” array, using zero for blank option

oMyPicklistCategory.push(0,1,2,3); // "0" doesn't actually exist - requires special processing...

Beginning line 81:

if(oFood[i].value == oDesiredOptions[j])
{
	oTempArray[i] = true;
	oDesiredOptions.splice(j,1);
}else{
	// handle "blank" default options 
	if(oFood[i].value == "" && oDesiredOptions[j] ==0){
		oTempArray[i] = true;
		oDesiredOptions.splice(j,1);
	}
}
  Oliver wrote @

Wow, that was quick. Thanks, I appreciate your help. Will test soon.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: