Como hacer picklist dinámicos en Microsoft CRM 3.0

El otro día me plantearon esta cuestión ¿Cómo puedo hacer que los valores de un picklist (lista desplegable) varíen en función de los valores de otro picklist? Al recibirla me puse a pensar, y recordé que en alguna parte había visto un ejemplo de cómo conseguir esto. Así que me puse a buscar donde lo había visto para responder a la pregunta. Después de un rato buscando, encontré esta entrada del blog de Ben Vollmer donde explicaba cómo conseguirlo.


La solución que proponía Ben Vollmer está muy bien, de hecho, me parece una de las formas más elegantes de conseguirlo. Pero al probarla descubrí un pequeño problema, nada grave, que consistía en que al abrir un registro en modo de actualización un registro se perdía la selección hecha en la lista dinámica. Así que basándome en la idea y el código de Ben Vollmer he creado un ejemplo sobre cómo conseguir picklist dinámicos solucionando ese pequeño problemilla.


¿Qué es un picklist dinámico? Básicamente es hacer que las opciones que se presentan en un picklist varíen de forma dinámica según alguna opción que elija un usuario (otro picklist, checkbox, etc…). Por ejemplo, tenemos un picklist donde se puede elegir el sector al que pertenece una cuenta y otro en el que podemos elegir el subsector. La idea es que al elegir un sector en el picklist de subsectores solo se muestren los que correspondan a ese sector. En este ejemplo haremos esto, es decir, que varíen las opciones de un picklist en función de otro picklist, pero la idea sería la misma en otras situaciones.




Antes de seguir, decir que al final del post podéis encontrar un enlace para descargaros la demos (código y personalizaciones).


Para construir nuestro ejemplo vamos a crear una entidad nueva en el CRM llamada “Demo Picklist”, y le vamos añadir dos campos de tipo picklist: uno llamado “lista” y otro “sublista”. Como es evidente, el objetivo es que las opciones que se muestran en la sublista varíen según la opción seleccionada en la lista. Al crear los picklist debemos indicar todas las opciones disponibles en la lista y en la sublista, pero es muy importante que las de la sublista vayan en orden con respecto a las de la lista, tal y como vemos en la siguiente tabla.















































 Lista  Sublista
 Nº Opción  Texto  Nº Opción  Texto
 1  Elemento 1  1  Elemento 1-1
 2  Elemento 1-2
 3  Elemento 1-3
 2  Elemento 2  4  Elemento 2-1
 5  Elemento 2-2
 6  Elemento 2-3
 3  Elemento 3  7  Elemento 3-1
 8  Elemento 3-2

Como se ve en la tabla, por cada opción de la lista tenemos una serie de opciones correspondientes en la sublista. Es muy importante que las opciones de la sublista vayan agrupadas (ordenadas) en función de la opción de la lista a la que pertenecen para facilitar el trabajo posterior de filtrar opciones a mostrar en la sublista.


Bien, ya tenemos creados los picklist y los hemos añadido al formulario ¿Qué código JScript necesitamos para hacer funcionar el invento? Lo primero será añadir código al onload() del formulario para poder hacer las inicializaciones necesarias. En este código debemos de hacer una copia del conjunto completo de opciones de la sublista para poder recuperar en cada momento las que necesitemos, para ello copiamos el valor de la propiedad Options en la propiedad originalPicklistOptions, así podremos recuperarlas cuando nos hagan falta. Además, si ya tenemos seleccionado un valor en la lista debemos de limitar el conjunto de opciones de la sublista (llamando al onchange de la lista, como veremos más adelante) y si no deshabilitarla. Básicamente es lo que hace el siguiente código.







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
var CRM_FORM_TYPE_CREATE = 1;
var CRM_FORM_TYPE_UPDATE = 2;

// Solo habilitamos el picklist dinamico para formularios de creacion o
// actualizacion, para el resto no es necesario.
switch (crmForm.FormType)
{
  case CRM_FORM_TYPE_CREATE:
  case CRM_FORM_TYPE_UPDATE:

    // Obtener referencia a la lista maestra
    var lista = crmForm.all.new_lista;
    // Obtener referencia a la sub lista
    var sublista = crmForm.all.new_sublista;

    // Guardamos el conjunto completo original de opciones de la sublista
    // utilizando la propiedad originalPicklistOptions
    sublista.originalPicklistOptions = sublista.Options;

    // Si no hay ningun valor seleccionado en la lista
    // deshabilitamos la sublista. Se volvera a habilitar
    // cuando el usuario seleccione un valor
    if (lista.DataValue == null)
    {
      sublista.Disabled = true;
    }
    else
    {
      // Ya tenemos seleccionado un valor, debemos limitar el conjunto
      // de iopciones de la sublista. Para ello disparamos el evento
      // onchange de la lista.

     // Almacenamos el valor seleccionado en la sublista
     var temp = sublista.DataValue;
    
     // Disparamos el onchange para limitar las opciones
      new_lista_onchange0();
      
      // Volvemos a fijar la opcion que estaba seleccionada
      sublista.DataValue=temp;
    }

  break;
}


Nota: El problema, que tenía el código de Ben Vollmer era que le faltaban las líneas 29 y 35, lo que hacía que cuando estábamos en un formulario de actualización se perdiese la opción seleccionada en la sublista.


Ahora tenemos que escribir el código para el onchage de lista. Este código se encargará de que cada vez que se modifique el valor seleccionado en la lista se establezcan las posibles opciones en la sublista. Gracias a que introducimos en orden los valores de la sublista, lo que tenemos que hacer es elegir un subarray del array original de opciones de la sublista (que en el onload convenientemente copiamos a la propiedad originalPicklistValue) basándonos en la opción seleccionada en la lista. Por ejemplo, para la opción 1 de la lista el array sería del elemento 1 al 3. Y una vez que tenemos el array no hay más que asignárselo al array Options de la sublista. ¡Y listo¡ Ya tenemos picklist dinámico. El código es el siguiente.







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// En funcion de el elemento seleccionado en la lista, escogeremos las opciones que se muestran
// en la sublista.
var lista = crmForm.all.new_lista;
var sublista = crmForm.all.new_sublista;
var comienzo = -1;
var fin = -1;

// Para facilitar la tarea las opciones de la sublista estan agrupadas en orden de correspondencia
// con las opciones de la lista, así que solo tenemos que elegir un rango de opciones de la
// sublista en función de las opcion de la lista
switch (lista.DataValue)
{
  case “1”:
    comienzo = 1;
    fin = 3;
    break;

  case “2”:
    comienzo = 4;
    fin = 6;
    break;
    
  case “3”:
    comienzo = 7;
    fin = 8;
    break;
}


// Si tenemos indices limitamos las opciones de la sublista
if (comienzo > -1 && fin > -1)
{
  // Creamos un array temporal donde almacenar las opciones
  var tempArray = new Array();

  // Inicializar indice para el array temporal
  var indice = 0;

  // Ahora recorremos la lista original de opciones de la sublista que
  // cacheamos en el onload del formulario y recogemos las que
  // perteneces a la opcion seleccionada en la lista
  for (var i = comienzo; i <= fin; i++)
  {
    tempArray[indice] = sublista.originalPicklistOptions[i];
    indice++;
  }

  // Copiamos el subconjunto de opciones seleccionado
  sublista.Options = tempArray;

  // Habilitamos la sublista
  sublista.Disabled = false;
}
else
{
  // No se ha seleccionado una opción en la lista, o la opcion no es valida
  sublista.DataValue = null;
  sublista.Disabled = true;
}


Para facilitar la labor, os dejo un zip con el código, y un fichero xml con la personalización de prueba para que podáis importarla en vuestro sistema y ver el funcionamiento. Y ahora os digo lo típico (es que me hace ilusión ponerlo): Este código se proporciona tal cual, sin garantía de ningún tipo. No es recomendable utilizarlo en un sistema en producción sin haberlo probado primero. Y leed el leeme.doc.


¿Qué os parecen los picklist dinámicos? ¿Algún bug en el código? Espero vuestras opiniones, correcciones, etc..


Un saludo,


Marco Amoedo

5 comentarios en “Como hacer picklist dinámicos en Microsoft CRM 3.0”

  1. Tengo dudas con la linea:

    // Disparamos el onchange para limitar las
    // opciones

    new_lista_onchange0();

    Necesito disparar este evento en un TextBox desde una ventana externa al CRM, puedo setear el texto con:

    window.opener.document.forms[0].all.new_dirswap.DataValue=’Texto’;

    pero al disparar un evento me da un error de JavaScript:

    window.opener.document.forms[0].all.new_dirswap_onchange0();

    Es posible??

  2. Hello

    My name is Ana and I started to work with the Microsoft CRM application recently.

    In one of my research I found your Blog, and since then, when I have a problem with my clients I try to find there, a solution for it.

    Today I try to find a solution to solve a similar question with another posted in your blog “Como hacer picklist dinámicos en Microsoft CRM 3.0”, I need something similar but with lookups. I need to have the possibility to select more of one option.
    In the first time I´ll select one option but in the second selection I want have the possibility pick more than one.
    Have you already try to make something like this, and it´s possible?

    Can you please help me?

    Thank You very much.

    Un saludo!

    Ana Pinto

  3. Hola!!

    No se si pueda aplicar esta solucion a lo que requiero, pero mi problema es el siguiente:

    Tengo un proceso de ventas en las cual se deben de cumplir ciertas tareas antes de que cambie la probalibidad al 10, 20, 40,60, 80 y al 100 %,

    lo que tengo que hacer es que cuando tengo una nueva oportinidad en la cual si se cumple que es de la empresa PATO y ademas que la oferta es PATO especial ASP entonces asignarme el 60% de la probabilidad en el proceso de ventas y pueda desactivar en el proceso de ventas las tareas o actividades anteriores.

    lo que he hecho es que en el evento Onsave de opportunity le dije que si se cumple esta condicion entonces me deje salvar la informacion, el punto es que no encuentro la forma de decirle que automaticamente asigne la probabilidad al 60% y que en el proceso de ventas las actividades anteriores o tareas no las ejecute y las ponga como no aplique.

    En que parte del CRM de customization y donde y con que herramienta poder hacer este cambio

    Agradezco su atencion prestada al mismo

    Saludos Cordiales

    Leticia

  4. Si necesito que un picklist muestre opciones pero no dependiendo del valor de otro picklist sino de un valor que se encuentra almacenado en otra entidad como lo puedo hacer? ej. cuando seleccione el producto en la oportunidad, el picklist debe mostrar unas opciones dependiendo del tipo de producto seleccionado, siendo el tipo un campo asociado con el producto.

    Gracias.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *