Mostrando entradas con la etiqueta Javascript. Mostrar todas las entradas
Mostrando entradas con la etiqueta Javascript. Mostrar todas las entradas

martes, 26 de mayo de 2015

Utilizando el Javascript en los Subgrids

El Update 1 de Dynamics CRM 2015 disponible solamente para online, tiene muchas mejoras en la SDK. Este tipo de mejoras son muy agradecidas por nosotros los desarrolladores, que nos aportan nueva y potentes funcionalidades que ofrecer a nuestros clientes.

Una de las mejoras que considero muy importantes, que no han sido muy publicadas, son las de las mejoras en código Javascript con el trabajo con los Subgrids.

Los Subgrids, son vistas que se pueden añadir en los formularios de CRM, por ejemplo para ver las actividades, contactos, o cualquier entidad relacionada de un registro.

Básicamente la idea es poder acceder a los Subgrids por código, y trabajar con el mismo, además de poder añadir código en el evento “OnLoad” de los Subgris (que se cargan de forma asíncrona).

El modelo de objetos de Javascript es el siguiente:


Aquí os dejo un pequeño (muy pequeño) código Javascript en donde he probado algunas de estas nuevas funcionalidades;
   1:  var onLoadSubGrid = function () { 
   2:      alert("Load subGrid");
   3:  };
   4:   
   5:  function onLoadForm()
   6:  {
   7:      var contactsSubgrid = Xrm.Page.getControl("Contacts");
   8:      contactsSubgrid.addOnLoad(onLoadSubGrid);
   9:  }
  10:   
  11:  function onChange()
  12:  {
  13:      var contactsSubgrid = Xrm.Page.getControl("Contacts");
  14:      alert ("Total de contactos: "+contactsSubgrid.getGrid().getTotalRecordCount());
  15:  }

  
Finalmente, lo que podemos hacer ahora es:
  • Acceder al Grid para ver la vista seleccionada, añadir eventos en el load, etc.
  • Acceder a los elementos de la vista, cuantos registros hay, cuales están seleccionados, etc
  • Acceder a los datos de los subgrids (GridEntity) con los campos entityType, id y name
  • Cambiar las vistas seleccionadas
El artículo de la SDK que ofrece mas detalles de estas mejoras está aquí: https://msdn.microsoft.com/en-us/library/dn932137.aspx y aquí con mas detalle: https://msdn.microsoft.com/en-us/library/dn932126.aspx
@demian_rasko

sábado, 19 de julio de 2014

Botón para reactivar Citas desde la barra de comandos

Una de las cosas que mas me gustan de colaborar en las comunidades de Dynamics CRM, es que cada día aprendo cosas nuevas.

Y cuando digo cada día, es CADA DÍA! hace poco me han comentado que las actividades podrían ser reabiertas, y esto es algo que antiguamente no se podía hacer, pero que en algún momento de las releases, rollups, etc. lo han abierto.

Esta funcionalidad abre un montón de nuevas oportunidades, como por ejemplo que se puedan reabrir actividades desde workflows.

En este caso, lo que voy a hacer es crear un botón en el “Command bar” para reactivar una Cita ya cerrada.

Para esto lo primero que tengo que hacer es añadir el botón en ese menú con el Ribbon Workbench :

image

La configuración del botón sería la siguiente:

image

El comando a llamar sería una función de Javascript llamada “Activar”:

image

La regla de visualización y activación del botón estarán relacionadas al estado del registro, en este caso, solamente se mostrará cuando el registro este desactivado (Completado):

image

Publicamos, y de esta manera ya tenemos un nuevo botón relacionado con Citas completadas (en el formulario).

Por otra parte, tengo un WebResource (new_actividad.js de javascript) con el siguiente código:

function Activar(Id)
{
   var EntityName="appointment";
   var State="3";
   var Status="5";
  
   
    SetStateRequest(EntityName, Id, State, Status);
 
    window.location.reload(true);

}

function SetStateRequest (_entName,_entId,_state, _status) {
    var requestMain = ""
    requestMain += "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
    requestMain += "  <s:Body>";
    requestMain += "    <Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
    requestMain += "      <request i:type=\"b:SetStateRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\" xmlns:b=\"http://schemas.microsoft.com/crm/2011/Contracts\">";
    requestMain += "        <a:Parameters xmlns:c=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
    requestMain += "          <a:KeyValuePairOfstringanyType>";
    requestMain += "            <c:key>EntityMoniker</c:key>";
    requestMain += "            <c:value i:type=\"a:EntityReference\">";
    requestMain += "              <a:Id>" + _entId + "</a:Id>";
    requestMain += "              <a:LogicalName>" + _entName + "</a:LogicalName>";
    requestMain += "              <a:Name i:nil=\"true\" />";
    requestMain += "            </c:value>";
    requestMain += "          </a:KeyValuePairOfstringanyType>";
    requestMain += "          <a:KeyValuePairOfstringanyType>";
    requestMain += "            <c:key>State</c:key>";
    requestMain += "            <c:value i:type=\"a:OptionSetValue\">";
    requestMain += "              <a:Value>" + _state + "</a:Value>";
    requestMain += "            </c:value>";
    requestMain += "          </a:KeyValuePairOfstringanyType>";
    requestMain += "          <a:KeyValuePairOfstringanyType>";
    requestMain += "            <c:key>Status</c:key>";
    requestMain += "            <c:value i:type=\"a:OptionSetValue\">";
    requestMain += "              <a:Value>" + _status + "</a:Value>";
    requestMain += "            </c:value>";
    requestMain += "          </a:KeyValuePairOfstringanyType>";
    requestMain += "        </a:Parameters>";
    requestMain += "        <a:RequestId i:nil=\"true\" />";
    requestMain += "        <a:RequestName>SetState</a:RequestName>";
    requestMain += "      </request>";
    requestMain += "    </Execute>";
    requestMain += "  </s:Body>";
    requestMain += "</s:Envelope>";
    var req = new XMLHttpRequest();
    req.open("POST", _getServerUrl(), false)
    // Responses will return XML. It isn't possible to return JSON.
    req.setRequestHeader("Accept", "application/xml, text/xml, */*");
    req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
    req.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");
    var successCallback = null;
    var errorCallback = null;
    req.onreadystatechange = function () { SetStateResponse(req, successCallback, errorCallback); };
    req.send(requestMain);
}

function SetStateResponse   (req, successCallback, errorCallback) {
    if (req.readyState == 4) {
        if (req.status == 200) {
            if (successCallback != null)
            { successCallback(); }
        }
        else {
          
        }
    }
}
function _getServerUrl   () {
    var OrgServicePath = "/XRMServices/2011/Organization.svc/web";
    var serverUrl = "";
    if (typeof GetGlobalContext == "function") {
        var context = GetGlobalContext();
        serverUrl = context.getServerUrl();
    }
    else {
        if (typeof Xrm.Page.context == "object") {
            serverUrl = Xrm.Page.context.getServerUrl();
        }
        else
        { throw new Error("Unable to access the server URL"); }
    }
    if (serverUrl.match(/\/$/)) {
        serverUrl = serverUrl.substring(0, serverUrl.length - 1);
    }
    return serverUrl + OrgServicePath;
}

Publicamos todo, y ahora voy a una Cita Completada:

image

Y haciendo “click” en el botón “Activar”, conseguimos reabrir la Cita:

image

La solución no administrada completa la dejo disponible para la descarga:

domingo, 11 de mayo de 2014

Utilizando la nueva librería Sdk.Soap.js

Avatar of Microsoft Dynamics CRM SDK Documentation Team
Hola, hoy voy a hablar acerca de la nueva librería para Dynamics CRM publicada recientemente en el Blog del equipo de Dynamics CRM: http://blogs.msdn.com/b/crm/archive/2014/04/28/new-microsoft-crm-sdk-sample-sdk-soap-js.aspx
El equipo de documentación de Dynamics CRM, lleva unos meses trabajando sobre esta solución, y la verdad que el resultado es excelente.
La idea de esta librería es ofrecer funcionalidades pre construidas y sencillas de reutilizar, para trabajar con los web services SOAP de Dynamics CRM desde javascript.
Otro de los objetivos es que la sintaxis a utilizar, sea muy similar a la que se utiliza al trabajar con la SDK desde C#, por lo tanto, gente que no conozca jQuery o no sea experto en Javascript pero que trabajen con C#, pueden trabajar con la misma.
Si entramos en profundidad en la documentación, podemos dividirla en 4 partes:
1) Sdk.Soap.js: Contiene el núcleo de esta nueva librería, que por sí sola ya permite ser utilizada.
2) Sdk.Soap.js Entity Class Generator: Para generar una clase en Javascript para trabajo con “early-bound”, similar al utilizado en C# “CRMSvcUtil.exe”. Como no trabajo con “early-bound” y sinceramente no lo recomiendo, no lo he probado.
3) Sdk.Soap.js Action Message Generator: Para la generación de “proxys” para las llamadas a las Acciones personalizadas (Custom Actions)
4) Sdk.Soap.js Samples: Ejemplos de utilización de la librería.
Ok, una vez realizada esta introducción, os voy a mostrar y compartir una solución basada en los ejemplos disponibles, pero simplificados, ya que son un poco mas complejos.
Los ejemplos que trae por defecto son muy completos, pero después hay que montarlos en CRM, por ejemplo en un WebResource, por esto, os planteo un ejemplo sencillo. Voy a crear, consultar (retrieve), actualizar y eliminar una Cuenta utilizando esta librería. Intentaré explicar paso a paso como lo he realizado y explicaré partes del código.
Primero os voy a enseñar lo que contiene mi solución y como se ejecuta:
image
Mi solución solo contiene:
  • new_Sdk.Soap.min.js: Contiene el “core” de esta solución, disponible para su descarga desde los enlaces anteriores
  • new_SdkSoapLibrary_Test.html: Es el HTML del web resource que he creado
  • new_Testing.js: Mi código javascript que realiza las llamadas CRUD para este ejemplo
Si abro el web resource HTML y lo ejecuto ve lo siguiente:
image
El HTML es muy sencillo y es el siguiente:
<html>
<head>
    <title>Ejemplo Late Binding</title>
    <script src="ClientGlobalContext.js.aspx" type="text/javascript"></script>
    <script src="new_Sdk.Soap.min.js"></script>
    <script src="new_Testing.js"></script>
    <script type="text/javascript">
        function Ejemplo() {
            document.getElementById("messages").innerHTML = "";
            writeToPage("Ejecutando Ejemplo Late Binding ");
            createAccount();
        }
    </script>
     <style>
            body {font-family: "Segoe UI";}
            table, th, td {border: solid 1px black;border-collapse: collapse;}
        </style>
</head>
<body>
    <button id="start" onclick="Ejemplo()">Ejecutar Ejemplo</button>
    <ol id="messages" />
</body>
</html>



Lo básico es la llamada a “createAccount” que es el que llama a mi código Javascript dentro de new_Testing.js.


Para el desarrollo con esta librería, recomiendo añadir en los ficheros Javascript la siguiente referencia, que permite trabajar y tener disponible el IntelliSense de toda la funcionalidad:


image


Si quiere trabajar con “entidades” con “late-bound”, dispongo de un objeto “Entity”, y es muy posible que a partir de aquí ya les empiecen a sonar temas ya que es lo casi mismo que con C#:

var account = new Sdk.Entity("account");

Si quiere crear una Cuenta con algunos datos, lo puedo hacer primero creando los datos de la entidad:

    account.addAttribute(new Sdk.String("name", name));
    account.addAttribute(new Sdk.Boolean("creditonhold", false));
    account.addAttribute(new Sdk.Double("address1_latitude", 47.638197));
    account.addAttribute(new Sdk.Double("address1_longitude", -122.131378));
    account.addAttribute(new Sdk.Int("numberofemployees", 100000));
    account.addAttribute(new Sdk.String("description", "This is a description. \n It has several lines. \n This is the third line."));
    account.addAttribute(new Sdk.Money("creditlimit", 2000000));
    account.addAttribute(new Sdk.OptionSet("accountcategorycode", 1)); //Preferred Customer

Esto es un poco “molesto”, ya que para cada tipo de dato, hayq eu añadir el “SDK.<type>” para crear los objetos. La librería nos ofrece una forma para poder simplificar esto, en donde, primero me defino los metadatos con los que trabajar, y luego mediante un método llamado “initializeEntity”, podemos trabajar de la siguiente manera:

    account.setValue("name", "Sample Account 001");
    account.setValue("creditonhold", false);
    account.setValue("address1_latitude", 47.638197);
    account.setValue("address1_longitude", -122.131378);
    account.setValue("numberofemployees", 100000);
    account.setValue("description", "This is a description. \n It has several lines. \n This is the third line.");
    account.setValue("creditlimit", 2000000.00);
    account.setValue("accountcategorycode", 1); //Preferred Customer

Es hacer lo mismo, pero de dos formas diferentes. Obviamente, la segunda parece ser algo mas limpia para mi gusto ya que trabajamos directamente con los tipos nativos de Javascript.

Luego ya la funcionalidad es sencilla, ya que una vez definidos estos objetos podemos hacer la llamadas a lo que necesitemos por ejemplo:

Create:

Sdk.Async.create(
     account,
     retrieveAccount);

Retrieve:

Sdk.Async.retrieve(
     "account",
     createdAccountId,
     getColumnSet(accountColumns),
     updateAccount );

Delete (se llama “del” ya que delete puede ser una palabra reservada de Javascript):

Sdk.Async.del("account", createdAccountId,
        deletedAccount_End);
Toda la solución, la dejo compartida como no administrada aquí.
Espero les sirva como introducción ya que la librería es muy completa, un abrazo!

sábado, 19 de abril de 2014

Funcionamiento avanzados de los sub Grids

No se si les ha ocurrido, pero por si les ocurre en algún momento, voy a explicar como funciona una funcionalidad de las que mas me gusta de Dynamics CRM 2013.

Es la funcionalidad de poder relacionar rápidamente registros “hijos” desde un formulario.

Añadir un registro existente a uno padre, consiste básicamente en cambiar ese campo “Lookup” del hijo, para relacionarlo con un nuevo registro “padre”.

Básicamente me refiero que teniendo una Cuenta por ejemplo si quiero añadirle ventas, lo que tengo que hacer es lo siguiente:

imageimage

Pero hay veces que al darle al “+” inicial, en vez de abrirnos eso, nos abre directamente el formulario de Creación rápida de la entidad (si lo tiene habilitado) o el formulario de creación principal.

Otra opción para probar es abrir el grid y ver que ocurre allí:

imageimage

Desde allí tengo la misma experiencia. La pregunta es, ¿por qué algunas relaciones se comportan así y otras nos permiten añadir de esta forma mas rápida?

La respuesta es sencilla, y depende del tipo de relación con el hijo. Si el Lookup que define la relación, lo definimos como “Requerido por la empresa”, el comportamiento cambia y esta funcionalidad deja de existir.

image

El botón de “Agregar…” desaparece, y al intentar añadir nuevos registros me abre el formulario de creación rápida:

imageimage

Por lo tanto, en este tipo de relaciones y formularios, al momento de personalizar formularios visualmente hay que tener en cuenta también si el campo es requerido o no.

Espero les sirva esto.

un saludo

viernes, 17 de enero de 2014

AngularJS en Dynamics CRM 2013

image
Imagino que casi todos ya lo conocen, y muchos ya lo utilizamos hace algún tiempo. AngularJs es un framework de javascript que permite trabajar con modelos MVC (Modelo Vista Controlador) de forma fácil y rápida.
La verdad que el mundo del javascript esta pegando los últimos años unas mejoras y expansión espectacular, y lo bueno de todo esto, es que Dynamics CRM está apoyado en todo esto y nos permite aprovecharnos de todo lo nuevo.
Lo que voy a hacer hoy es una especie de “Hola mundo”, aprovechando lo siguiente:
  • AngularJS (con su NGGrid)
  • jQuery
  • Ejemplos en javascript de la SDK de CRM
La idea funcional es mostrar en un Dashboard de CRM (Panel), un web resource, que recoja datos de CRM y mediante AngularJS, me cree un grid, con funcionalidades como agrupar, ordenar, etc.
Lo que finalmente obtengo es lo siguiente, un grid de Cuentas, con sus ciudades, y la posibilidad de ordenar y agrupar haciendo drag & drop, todo esto en un web resource dentro de un dashboard:
image
image
Como lo hice, es bastante sencillo. Primero empiezo con un web resource de tipo HTML con el siguiente código:
<html ng-app="myApp">  
    <head lang="en">
        <meta charset="utf-8">
        <title>CRM con AngularJS</title>  
        <link rel="stylesheet" type="text/css" href="new_nggrid.min.css" />
        <link rel="stylesheet" type="text/css" href="new_style.css" />
        <script src="ClientGlobalContext.js.aspx" type="text/javascript"></script>
        <script type="text/javascript" src="new_jquery2.0.3.min.js"></script>
        <script type="text/javascript" src="new_jqueryui1.9.1.custom.min.js"></script>
        <script type="text/javascript" src="new_angular.min.js"></script>
        <script type="text/javascript" src="new_nggrid2.0.7.min.js"></script>
        <script type="text/javascript" src="new_SDK.REST.js"></script>
        <script type="text/javascript" src="new_script.js"></script>
    </head>
    <body ng-controller="MyCtrl">    
        <div class="gridStyle" ng-grid="gridOptions"></div>
    </body>
</html>

En este HTML, lo importante es como llamo a mi aplicación “myApp” con el parámetro ng-app y luego el control “MyCtrl” con el parámetros ng-controller, que utilizaré luego.

Fácil, el tema es que hay que añadirle muchas librerías de javascript. Para esto, las añado como web resources en mi solución:

image

Todos esos javascript son librerías genéricas (angular, jquery, etc.) salvo una que llamé “script.js”. En este fichero voy a añadir la lógica de mi formulario:

var app = angular.module('myApp', ['ngGrid']);
app.controller('MyCtrl', function($scope, $http) {    $scope.totalServerItems = 0;
    $scope.pagingOptions = {
        pageSizes: [250, 500, 1000],
        pageSize: 250,
        currentPage: 1
    };    
     $scope.setPagingData = function(data, page, pageSize){    
        var pagedData = data.slice((page - 1) * pageSize, page * pageSize);
        $scope.myData = pagedData;
        $scope.totalServerItems = data.length;
        if (!$scope.$$phase) {
            $scope.$apply();
        }
    };
    $scope.getPagedDataAsync = function (pageSize, page, searchText) {
        setTimeout(function () {
            var number = 50;
             var options = "$select=Name,Telephone1,Address1_City&$top=" + number ;
             
            SDK.REST.retrieveMultipleRecords("Account", options, function (retrievedAccounts){
                
                $scope.setPagingData(retrievedAccounts,page,pageSize);
                }, function (error) { alert(error.message); }, function (res){var aux=1;});
         }, 100);
    };        
    $scope.gridOptions = {
        data: 'myData',
        enablePaging: false,
        showFooter: false,
        totalServerItems: 'totalServerItems',
        pagingOptions: $scope.pagingOptions,
        filterOptions: $scope.filterOptions, 
        
        columnDefs: [{field:'Name', displayName:'Name'}, {field:'Telephone1', displayName:'Telephone1'}, {field:'Address1_City', displayName:'Address1_City'}], 
        showGroupPanel: true, 
        jqueryUIDraggable: true, 
        enableCellSelection: true,
        enableRowSelection: false,
        enableCellEdit: true,
    };
});    
Este código consulta a CRM al punto oData, y el resultado que es un objeto jSON, lo meto en gridoptions con sus columnas definidas en “columnDefs”. Además en gridOptions se pueden añadir o quitar parámetros de comportamientos del grid, como paginaciones, ediciones, selección de líneas o celdas, etc.

Para mas información, recomiendo estudiarse a fondo este framework, a mí sinceramente me encante porque soy un amante del Javascript (http://angularjs.org/). Mirar también algo específico de ngGrid (Grid de AngularJS utilizado en este ejemplo).

Por último, como siempre, les dejo toda la solución no administrada para que podáis jugar: angulasJS_1_0_0_0.zip

Un saludo!

sábado, 28 de septiembre de 2013

Lógica de negocio portable en CRM 2013 (PBL Rules)

Una de las nuevas funcionalidades que mas me han sorprendido sobre CRM 2013, es lo conocido como “PBL (Portable Business Logic) Rules”.
Esta nueva funcionalidad ofrece la posibilidad de creación de formularios dinámicos con una arquitectura similar a la que yo tenía en la cabeza cuando desarrollé DynamicForm el año pasado (http://www.demianrasko.com/2012/08/dynamicform-tutorial-de-implantacion.html). La idea que tenía en la cabeza era que no haga falta que se desarrolle todo por Javascript desde cero, cada vez que se nos presentaban formularios que debían cambiar dependiendo de diferentes condiciones.
Bueno, Microsoft ya nos ofrece esta funcionalidad “OOB” (Out of the box), lo cual se agradece ya que además dispone de un interfaz de usuario muy amigable.
Los pasos para definir una nueva “Business Rule” son los siguientes:
1) Ir a las personalizaciones de la entidad y crear una nueva (en este caso en Cuenta)
image
2) Definimos una o varias condiciones que dispararán la regla (las condiciones se agrupan siempre con la condición “Y”)
image
Lo bueno y nuevo de estas condiciones, es que se pueden definir condiciones de comparaciones entre campos además de cadenas de texto fijas, por ejemplo en el caso que muestro, estoy definiendo la condición de que el Teléfono principal sea igual al Fax.
3) Definir la Acción o acciones a realizar. Las acciones pueden ser de diferente tipo:
Para mostrar mensajes de error en los atributos:
image
Para poner valores en campos:
image
Para definir campos como obligatorios o no obligatorios:
image
Para definir la visibilidad de los campos:
image
Para bloquear o desbloquear campos del formulario:
image
Una vez definida nuestra regla de negocio, se ve así:
image
Allí se ve que en la parte superior derecha, se puede definir para que formulario se aplicará esta regla (o todos).
Una vez guardado, debemos activarlo para ponerlo en funcionamiento:
image
Una vez activado, no hace falta publicar la entidad, y ya lo tenemos disponible, a continuación muestro lo que ocurre.
Cuando se abre el formulario de una Cuenta se ve así:
image
Luego modifico el campo “Fax” al mismo valor que tiene el campo “Phone” (333) y lo que ocurre es lo siguiente:
image
Como aclaración adicional, hay que tener en cuenta que los javascript que tengamos en el load() del formulario se disparan después de la ejecución de las PBL Rules (salvo lo de mostrar los mensajes de error, que aparecen después). A continuación se puede ver como mi javascript del “Load” que dispara un alert, se dispara, pero por debajo ya podemos ver que Ticker Symbol ya esta en solo lectura y obligatorio y el campo “Web site” está ya oculto:
image
Como siempre, intento ir un poco mas lejos. He creado un Javascript en el load, que pone un valor
   1: function carga()
   2: {
   3:     alert("load");
   4:     Xrm.Page.getAttribute("telephone1").setValue("333");
   5:     alert("cambiado el valor de Phone");
   6: }
 
 
Entonces inicialmente Phone y Fax tienen valores diferentes:
image
Luego cambio el valor por javascript y quedan iguales, pero la regla PBL no se ha disparado (porque el “pbl rule” se ejecutó antes):
image

Para que se ejecute la regla de negocio, se deberá disparar el “Onchage” del campo Phone.

Por esto último, habrá que tener cuidado con mezclar Reglas de negocio PBL y código javascript, teniendo en cuenta también que los PBL se ejecuta o actualizan solamente en el Load (antes de los load() de javascript) y en los onchange de los campos.
Los PBL Rules son parte de las personalizaciones de una entidad, como las vistas, formularios o campos. Por lo tanto viajan en las soluciones con las entidades a las que pertenecen.

Estas funcionalidades nos permiten que usuarios sin conocimientos de desarrollo en Javascript, puedan crear formularios mas dinámicos.

miércoles, 16 de enero de 2013

Mostrar usuario actual (logueado) en un Lookup

Hola, a veces en los formularios de Dynamics CRM necesitamos recoger el usuario actual o logueado para rellenar algún lookup con ese valor.
Hoy voy a plantear un ejemplo completo de esto y de como se puede resolver.
Lo primero que hay que hacer es la creación de un campo de tipo Lookup con usuario en la entidad de Cuenta:
image
Luego lo añadimos al formulario de Cuenta:
image
Finalmente debemos añadir el siguiente javascript que se ejecute en el Load para actualizar el valor del campo:
   1: function setUsuarioActual()
   2: {
   3:    var user = Xrm.Page.context.getUserId(); 
   4:    var userId = user.substring(1,37);
   5:    var serverUrl = Xrm.Page.context.getServerUrl()
   6:     var ODATA_ENDPOINT = "/XRMServices/2011/OrganizationData.svc";
   7:     var ODATA_EntityCollection = "/SystemUserSet";
   8:     // Specify the ODATA Query
   9:     var ODATA_Query = "(guid\'" + userId + "')";
  10:     // Combine into the final URL
  11:     var ODATA_Final_url = serverUrl + ODATA_ENDPOINT + ODATA_EntityCollection + ODATA_Query;
  12:  
  13:     //Calls the REST endpoint to retrieve data
  14:     $.ajax({
  15:         type: "GET",
  16:         contentType: "application/json; charset=utf-8",
  17:         datatype: "json",
  18:         url: ODATA_Final_url,
  19:         beforeSend: function (XMLHttpRequest) {
  20:             XMLHttpRequest.setRequestHeader("Accept", "application/json");
  21:         },
  22:         success: function (data, textStatus, XmlHttpRequest) {
  23:            var userName = data.d.FullName;
  24:            Xrm.Page.getAttribute("new_usuarioactualid").setValue( [{id: userId , name: userName , entityType: "systemuser"}]);
  25:  
  26:            },
  27:         error: function (XmlHttpRequest, textStatus, errorThrown) {
  28:             alert('Error: '+ ODATA_Final_url);
  29:  
  30:             }
  31:     });
  32:  
  33:  
  34: }
 

Añadirlo en un web resource y llamar a ese método en el load:

image

Por cierto, para que este código funcione, hay que añadir también la librería de jQuery.
Finalmente al abrir el formulario de las Cuentas, el campo “Usuario Actual” se rellena como se ve:


image


Un abrazo!

lunes, 20 de agosto de 2012

DynamicForm: Tutorial de implantación

Completando el artículo del otro día, lo que voy a hacer hoy es explicar como implementar paso a paso (“Step by Step”) la librería y como ponerla en funcionamiento.

La primera opción, podría ser el descargarse la solución completa de Codeplex y luego importarla: http://elblogdedynamicscrm.codeplex.com/releases/view/87885

La versión actual es la DynamicForm_2_1_0_0.zip. Importando y publicando la misma, ya podéis ver funcionando todo lo explicado en el formulario de Cuentas. Solo haría falta crearse algunos países en la entidad con el mismo nombre.

Tener en Cuenta que la solución tiene personalizaciones en Cuenta y Países, además de crear algunos web resources y en es “No Administrada”, por lo cual no se podrá desinstalar:

image

Otra opción pasaría por implementarlo poco a poco y a “mano”. La idea es mostrar como implementar la librearía en el caso real con los ejemplos que ya he montado yo. Esto permitirá entender como funciona.

Los pasos serían los siguientes:

1) Creación de WebResource DynamicForm:

image

El código fuente que se debe incluir en el mismo está en codeplex en el fichero DynamicForm_2.1.js: http://elblogdedynamicscrm.codeplex.com/SourceControl/changeset/view/14049#219034

2) Creación Web Resource con jquery:

image

El código fuente que se debe incluir en el mismo está en codeplex en el fichero jquery.js:

http://elblogdedynamicscrm.codeplex.com/SourceControl/changeset/view/14185#227690

3) Creación del Web Resource ReadDataSyncFunctions

image

El código fuente que se debe incluir en el mismo está en codeplex en el fichero ReadDataSyncFunctions.js:

http://elblogdedynamicscrm.codeplex.com/SourceControl/changeset/view/14186#227691

4) Creación del Web Resource con el XML de configuración

image

El código fuente que se debe incluir en el mismo está en codeplex en el fichero new_test_xml.xml:

http://elblogdedynamicscrm.codeplex.com/SourceControl/changeset/view/14187#227692

5) Creación de la entidad de Países:

image

6) En Cuentas se deben crear dos atributos, uno de tipo Lookup a Paises y otro de tipo ntext:

image

7) Personalizaciones en el formulario de Cuenta para añadir funcionalidades

En la siguiente imagen muestro como he dejado el formulario de cuentas, y he marcado los IFRAMES que he creado con sus nombres.

image

La configuración de los 3 IFRAMES es similar y es como lo siguiente:

imageimageimage

La idea es que en el formulario, estén añadidos todos los campos, secciones y pestañas utilizados en el XML anterior. Además es necesario crear los IFRAMES donde se incluirán las funcionalidades de combo, radio y múltiple selección.

8) Añadir los recursos web con el javascript que se utilizará en el formulario:

image

Es importante mantener el orden:

  • jquery
  • ReadDataSyncFunctions.js
  • DynamicForm

9) Añadir las llamadas necesarias en los eventos:

OnLoad y OnSave del formulario:

image

image

Y en los campos utilizados para las funcionalidades de la librería:

image

image

image

image

image

image

image

image

image

image

Espero les sirva este paso a paso a entender como está “montada” la solución y como funciona.

A partir de ahora intentaré ir mejorándola mas poco a poco.

Un abrazo a todos!

Demian.