Tag Archives: jQuery

SAMPLE: Editable grid for CRM 2011 using jqGrid

A while back, I wrote a post called Building an editable grid for CRM 2011.   The goal of the post was to give you the necessary knowledge to know how to write the code to build an editable grid.  Since then, someone introduced me to jqGrid.  This is quite a powerful JavaScript grid control.  Have a look at the site to see all the things you can do with it.

I’ve built a little sample for a customer using jqGrid.  I wanted to spend some time cleaning the code up and making it more reusable before I blogged about it.  My lofty goal was for it to be a fully reusable editable grid control for CRM.  My thinking was that all you would have to do is drop a web resource on the form, pass the web resource a set of parameters (child entity, columns to display, etc.), and the web resource would render a custom grid based on what you passed it.  Well, as most of my lofty goals for side projects go, I haven’t found the time to get it where I want it to be.  Since then I’ve promised a number of folks to at least share what I have until I can get around to turning this into what I want it to be. 

To get started, download the sample from here.  Unzip the contents somewhere.  If you want to open the Visual Studio solution, you will need the Developer Toolkit for Microsoft Dynamics CRM installed.   Make sure you read the README.txt file in the root of the CrmEditableGrid project.  As I say in the readme:

THIS IS NOT A FULLY REUSABLE EDITABLE GRID CONTROL.  IT IS A SAMPLE DEMONSTRATING HOW
TO USE THE FACILITIES OF THE CRM 2011 SDK COMBINED WITH A POPULAR JAVASCRIPT GRID CONTROL (jqGrid).
WITH THIS AS YOUR STARTING POINT, YOU SHOULD BE ABLE TO USE THE CRM 2011 SDK AND THE jqGrid
DOCUMENTATION TO ADD ADDITIONAL CAPABILITIES TO THE GRID SUCH AS: ADD/DELETE ROW, OPTION SETS, ETC.

To get the sample working, import the dkdteditablegrid.zip file into your CRM organization.  It’s an unmanaged solution.  Make sure you publish all customizations at the end of the import.  I didn’t export the sitemap so you will need to find the Parent entity and add it to the Workplace area to see it:

image

Make sure you publish and refresh the browser so the updates show up.  Ok, I warned you that this sample was incomplete.  To get the editable grid into a useable state, you need to create a Parent record and a couple related Child records.  Navigate to Workplace->Extensions->Parents and create a new parent.  Make sure you Save (not Save & Close).

image

Now navigate to Related->Common->Children and add a couple children.

image

Once you’ve added a couple children.  Close the form and open it again.  Like I said, work in progress.  What you’ll see is a grid on the form that looks something like this:

image

If you click the “e” button, then you’ll put the record in edit mode.  The “c” button cancels and the “s” button saves the record.  The way this works is as follows:

  • The grid is an html web resource that is passed the record id from the parent form
  • When the web resource loads, it makes an OData query for the children
  • Upon query completion, it wires up the data to the jqGrid
  • When “s” button is clicked, the code updates the child record through the OData service

The goal of this sample, for now, is to have enough of the core plumbing in place for you to take and elaborate to your specific scenario.  Once you realize how capable jqGrid is, then you’ll understand that it’s not that big of a leap forward to get to where you want to be.  I still plan to transform this from a code sample to something people can just pickup and use on many forms by passing a few parameters to the web resource.  Of course, time needs to be on my side…yes it does.  Let me know if you beat me to it! 

@devkeydet

Displaying a lookup as a dropdown in a CRM 2011 form

UPDATE (04JUN2013):  If you need to evolve this sample to support a one to many relationship represented as a multi-select, I like this multi-select control which can be themed with jQuery UI themes.

Another scenario from a customer:

We want to use a lookup to another entity because we want to store additional data in the  entities fields and option sets don’t provide this capability.  However, we want the selection of the entity in the form to be a dropdown to minimize the # of clicks a user must go through to select the entity.

HTML / JavaScript web resources and the OData service to the rescue!  First, this sample was loosely inspired by this post from my teammate Carlton Colter.  I took his idea, ran with it, applied it to this problem, and made my solution a reusable web resource that you can pass parameters to in order to apply it to any lookup on a form.  Here are the steps…

Add the lookup field to the form:

image

Notice that this lookup is required.  This solution respects the required metadata of the field and uses it to ensure the dropdown has a value before the form is saved.  Set the properties of the lookup making sure the Visible by default option is unchecked:

image

Insert an html web resource to the form with the following General settings configured (the code for the web resource is available further down):

image

The Custom Parameter(data) property is what makes this reusable.  You can figure out what needs to be passed in by looking at the JavaScript, but here is the comma separated format:

lookupEntitySetName,lookupEntityIdFieldName,lookupEntityDisplayFieldName,nameOfLookupFieldOnForm,webResourceName

Here is a longer description if the variable names aren’t clear enough:

lookupEntitySetName = Name of the entity set in the OData service for the entity.

lookupEntityIdFieldName = The id/primary key for the in the OData service.

lookupEntityDisplayFieldName = The field name from the entity that you want to display in the dropdown.

nameOfLookupFieldOnForm = The name of the actual lookup field that is hidden on the form.

webResourceName = The name of the web resource on the form.  This is set in the Add Web Resource dialog and always starts with WebResource_.

Make sure you set the properties on the Formatting tab like so:

image

Finally, there is a little bug that I gave up on.  So you will need to put a spacer next to or below the web resource:

image

This will prevent the dropdown for getting cut off if there is nothing to the right or bottom of it.  If it already has something to the right of it or below it, then this is unnecessary.  Bingo bango!  You now have a lookup that’s represented on the form as a dropdown complete with required validation:

image 

The dropdown is just UI trickery.  When you save the form, the value of the lookup is saved correctly.  In update scenarios, the form loads, reads the hidden lookup value, and sets the dropdown selected item appropriately.

Here’s the code for the html web resource:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<html>

    <head>

        <title></title>

        <script src="../ClientGlobalContext.js.aspx" type="text/javascript"></script>

        <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.min.js" type="text/javascript"/>

        <script src="scripts/dropdownforlookup.htm.js" type="text/javascript"/>

 

        <!-- TOOD: move the needed styles into our own stylesheet. The CRM team doesn't support referencing their styles because they can change -->

        <link href="/_common/styles/fonts.css.aspx?lcid=1033" rel="stylesheet" type="text/css"/>  

        <link href="/_common/styles/global.css.aspx?lcid=1033" rel="stylesheet" type="text/css"/>  

        <link href="/_common/styles/select.css.aspx?lcid=1033" rel="stylesheet" type="text/css"/>  

    </head>

    <body style="background-color: rgb(246, 248, 250); border-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-left: 0px; padding-top: 0px;">

        <!-- TOOD: move the needed styles into our own stylesheet. The CRM team doesn't support referencing their style sheets because they can change -->

        <select id="lookupdropdown" class="ms-crm-SelectBox">

            <option value="Loading..." selected="selected">Loading...</option>

        </select>

    </body>

</html>

Here’s the code for the dropdown.htm.js file that it references:

$(document).ready(function () {

    var context = GetGlobalContext();

    var params = context.getQueryStringParameters();

    // The data passed to the web resource should be in the following format:

    //

    // lookupEntityName,lookupEntityIdFieldName,lookupEntityDisplayFieldName,nameOfLookupFieldOnForm,webResourceName

    //

    var dataParam = params.data.split(",");

    var lookupEntitySetName = dataParam[0];

    var lookupEntityIdFieldName = dataParam[1];

    var lookupEntityDisplayFieldName = dataParam[2];

    var nameOfLookupFieldOnForm = dataParam[3];

    var webResourceName = dataParam[4];

 

    var oDataQuery = context.getServerUrl() + "/XRMServices/2011/OrganizationData.svc" +

    "/" + lookupEntitySetName + "?$select=" + lookupEntityIdFieldName + "," + lookupEntityDisplayFieldName;

 

    var lookupAttribute = window.parent.Xrm.Page.getAttribute(nameOfLookupFieldOnForm);

    var lookupArray = lookupAttribute.getValue();

 

    $.getJSON(oDataQuery, function (data) {

        var results = data.d.results;

        var lookupdropdown = $("#lookupdropdown");

 

        for (var i = 0; i < results.length; i++) {

            var option = "<option value='" + results[i][lookupEntityIdFieldName];

            option += "'>" + results[i][lookupEntityDisplayFieldName] + "</option>";

            lookupdropdown.append(option);

        }

 

        lookupdropdown.prepend("<option value='blank'></option>");

 

        if (lookupArray) {

            var lookupId = lookupArray[0].id.replace("{", "").replace("}", "").toLowerCase();

            lookupdropdown.val(lookupId);

        } else {

            lookupdropdown.val("blank");

        }

 

        $("#lookupdropdown option[value='Loading...']").remove();

 

        lookupdropdown.width("100%"); // couldn't figure out what was causing it to not stretch so I just forced it

 

        lookupdropdown.change(function () {

            var name = $("#lookupdropdown option:selected").text();

            if (name == "") {

                SetLookupValueToNull(nameOfLookupFieldOnForm);

            } else {

                var entityType = results[0].__metadata.type.replace("Microsoft.Crm.Sdk.Data.Services.", "");

                SetLookupValue(nameOfLookupFieldOnForm, lookupdropdown.val(),

                name, entityType);

            }

        });

    });

 

    var requiredLevel = lookupAttribute.getRequiredLevel();

 

    if (requiredLevel == "required") {

        // We want to drive whether our dropdown requires a value by the hidden lookup fields metadata

        // However, if we keep the lookup field's requirement level to required the form validation

        // will tell us it is required an force us to show it.

        lookupAttribute.setRequiredLevel("none");

 

        //NOTE: Modifying html that the CRM server sends down to the browser is not supported.

        // However, here we are finding a label for this control and updating its text.

        // This is relatively harmless and the likelihood of the CRM representing a label

        // for a control as anything other than an html label control is low. So I feel safe

        // enough to break the "don't touch the CRM html" rule. Even if it becomes an issue

        // at upgrade, we have one place where we can make the adjustments

        var label = $("label[for='" + webResourceName + "']", window.parent.document);

 

        // TODO: Improve this so it isn't tightly coupled to CRM generated html/css. Using undocumented css and server urls is unsupported.

        label.append("<IMG class=ms-crm-ImageStrip-frm_required alt=Required src='/_imgs/imagestrips/transparent_spacer.gif?ver=600790655'>");

 

        // TODO: add onsave to display an error message.

        window.parent.Xrm.Page.data.entity.addOnSave(function (context) {

            var name = $("#lookupdropdown option:selected").text();

            if (name == "") {

                var labelForWebResource = window.parent.Xrm.Page.getControl(webResourceName).getLabel();

                alert("You must provide a value for " + labelForWebResource + ".");

                context.getEventArgs().preventDefault();

            }

        });

    }

});

 

function SetLookupValue(fieldName, id, name, entityType) {

    if (fieldName != null) {

        var lookupValue = new Array();

        lookupValue[0] = new Object();

        lookupValue[0].id = id;

        lookupValue[0].name = name;

        lookupValue[0].entityType = entityType;

 

        window.parent.Xrm.Page.getAttribute(fieldName).setValue(lookupValue);

    }

}

 

function SetLookupValueToNull(fieldName) {

    if (fieldName != null) {

        window.parent.Xrm.Page.getAttribute(fieldName).setValue(null);

    }

}

@devkeydet

Showing a jQuery UI dialog in a CRM 2011 form

I was asked how to implement the following scenario in a CRM 2011 form (paraphrased):

  • Show an alert notification indicator in the header
  • When the user to click the notification indicator, show a dialog with the details of the alert

Here’s how I did it.  The code below assumes you’ve already wired up jQuery and jQuery UI to the form.

Add an html web resource to the header:

image

Configure the web resource properties:

imageimage

Here’s the markup for the html web resource:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<html>

    <head>

        <title></title>

        <script src="../ClientGlobalContext.js.aspx" type="text/javascript"/>

        <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.min.js" type="text/javascript"/>

        <script src="scripts/dialogfromheader.htm.js" type="text/javascript"/>

        

        <!-- TODO: move the needed styles into our own stylesheet.  The CRM team doesn't support referencing their styles because they can change -->

        <link href="/_common/styles/fonts.css.aspx?lcid=1033" rel="stylesheet" type="text/css"/>  

        <link href="/_common/styles/global.css.aspx?lcid=1033" rel="stylesheet" type="text/css"/>  

        <link href="/_common/styles/select.css.aspx?lcid=1033" rel="stylesheet" type="text/css"/>  

    </head>

    <!-- TODO: move the style info into our own stylesheet. -->

    <body style="background-color: rgb(246, 248, 250); border-width: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-left: 0px; padding-top: 0px;">

        <img id="alert" src="images/alert_icon_red.jpg" alt="alert icon"

             width="25px" height="25px" style="cursor:pointer"/>

    </body>

</html>

Here’s the code for the referenced dialogfromheader.htm.js script file:

$(document).ready(function () {

    // Execute an OData ajax query to determine if there are alert records (stored in a related entity)

    // You probably need to pass entity id to the page from the CRM form to compose a proper query

    // If alerts exist show the alert UI, otherwise do nothing

    // I am not doing that here, but it should be obvious enough

 

    // If you have results, build up the html to put in the dialog to represent the alerts information

    var htmlForTheDialog = "<p>PLACED HOLDER FOR THE ALERT HTML</p>";

 

    $("#alert").click(function() {

        window.parent.dkdt_showDialog(htmlForTheDialog);

    });

});

Add a JavaScript web resource to the form:

image

Here’s the code for the referenced dialogsetup.js script file:

function dkdt_wireupDialog() {

    // NOTE: This clearly deviates from the 

    // "don't touch the HTML generated by the CRM UI" guidance from the SDK

    // Typically, I urge people not to do this because it is technically unsupported.

    // However, in this case we're not really modifying the generated UI.

    // We are just adding a div to the body of the html.

    // I'm accepting that I am doing something that's unsupported, but still relatively low risk of side effects

    $("body").append("
"
);

    $("#dkdt_dialog").dialog({ autoOpen: false, position: "top" });

}

 

function dkdt_showDialog(dialogHtml) {

    $("#dkdt_dialog").html(dialogHtml);

    $("#dkdt_dialog").dialog("open");

}

Now, when an end user clicks on the alert icon they will see the alert details:

image

@devkeydet

OQuery – A fluent API to build OData url queries sans LINQ

Yesterday, I blogged about a solution to compose OData / WCF Data Service queries using LINQ for situations where LINQ enabled client libraries don’t exist (i.e. JavaScript and Windows Phone 7).

http://blogs.msdn.com/b/devkeydet/archive/2011/02/02/data-services-odata-client-for-windows-phone-7-and-linq.aspx

The post is all about using LINQPad as a tool to write your LINQ queries, then using the feature in LINQPad that gives you the url query translation.  Well today, a new MSDN Code Callery project just popped up called OQuery that offers another approach that doesn’t require using an external tool such as LINQPad:

http://code.msdn.microsoft.com/oquery

Here’s the description from the project page:

“OQuery is a library which gives you a fluent style interface for building OData Url Fragments in javascript or C#.
Neither Javascript or Silverlight for WP7 support LINQ and so this library in those cases.”

What are you waiting for?  Go check it out!

Follow devkeydet on Twitter

The unofficial biography of Microsoft, ASP.NET, Ajax, and jQuery

The Microsoft Ajax strategy has been a bit of a winding road.  Even if you’ve kept up with the evolution, as I have, you might be a little confused.  Today, Scott Guthrie published a blog post announcing that Microsoft’s first submissions to jQuery are official.  There was a corresponding blog post on the jQuery blog.  There’s also an overview video about the Microsoft submissions by Stephen Walther over on Ch.9.  What’s not covered in these posts is the historical evolution that brings us to what was announced today.  You may may be saying to yourself “So what?”  Well, the internet is full of blog posts on the topic.  Depending on the place in time when the blog post or article you come across via your favorite search engine (Bing of course) was published, you might be led astray.  Knowing what’s what and the history helps you from making the mistake of following stale information.  Dave Ward to the rescue!  He wrote up what I think if as the “unofficial biography” on the topic.  Definitely worth a read:

Javascript Libraries and ASP.NET: A Guide to jQuery, AJAX and Microsoft

Does jQuery ship with SharePoint 2010? (and why you should be using an Ajax CDN)

jQuery is one of the most popular javascript libraries used by ASP.NET developers.  In fact, jQuery ships with Visual Studio 2010.  It is in the “Scripts” folder of a new “ASP.NET Web Application” or “ASP.NET MVC 2 Web Application” project template.

Does jQuery ship with SharePoint 2010?  Short answer: No.  I see this asked (publicly and internally) a few times a month.  Long answer: You don’t need it to.  Just use it from the Microsoft Ajax CDN

Assuming you don’t have to build a solution on a closed network with no internet access, then one of the first things you should consider is to replace all the references in your code to local javascript files to CDN references.  By doing so you get the general benefit that all CDNs offer (not just Ajax CDNs) which is that you get directed to a server the is closer to you.  Also, since browsers cache files based on URL, referencing the CDN from all your code means that different web apps use the same version of the javascript file cached in the browser.  Last, but not least, it means less files you have to maintain on your own servers.

Here’s what a script reference to jQuery 1.4.2 looks like when it is local:

<script src="../../Scripts/jquery-1.4.1.min.js" type="text/javascript"></script>

Here’s what it looks like when referencing the CDN:

<script src="http://ajax.microsoft.com/ajax/jquery/jquery-1.4.2.min.js" type="text/javascript"></script>

So that’s how easy it is to reference jQuery from your SharePoint code.  However, as you can see, this applies way beyond just SharePoint programming.

Love jQuery = Love ASP.NET Ajax Library

digg_url = “http://blogs.msdn.com/devkeydet/archive/2010/02/03/love-jquery-love-asp-net-ajax-library.aspx&#8221;;digg_title = “Love jQuery = Love ASP.NET Ajax Library”;digg_bgcolor = “#555555”;digg_skin = “normal”;http://digg.com/tools/diggthis.jsdigg_url = undefined;digg_title = undefined;digg_bgcolor = undefined;digg_skin = undefined;

I’ve been covering ASP.NET AJAX and what used to be called the “Microsoft Ajax Library” ever since the first “Atlas” code drops.  ASP.NET AJAX has always offered Web Forms developers a relatively simple way of Ajax enabling their applications without forcing them to change how they write them through the the core Ajax Server Controls (ScriptManager, Timer, UpdatePanel, UpdateProgress), Ajax Extender Controls, and the 40 additional Server Controls in the ASP.NET AJAX Control Toolkit

What’s been lost in all of this is that all the magic that makes these server-side coding capabilities possible is what used to be called the “Microsoft Ajax Library.”  It’s a cross-browser JavaScript library that has always been available to use WITHOUT ASP.NET.  It’s just a set of JavaScript files that can be used with ANY web development technology.  Unfortunately, many people don’t realize it because there has been so much focus on ASP.NET AJAX (i.e. the integration of this core set of JavaScript libraries with ASP.NET to make AJAX for ASP.NET Web Forms easier).

Ok, on to my point about love and jQuery.  The next release of the ASP.NET Ajax Library has a heavy focus on making client-side Ajax programming easier. I’ve become a big fan of using jQuery and the jQuery syntax for client-side JavaScript.  There is very little overlap between jQuery and the ASP.NET Ajax Library.  They are a very complimentary match.  One of the many new capabilities in the ASP.NET Ajax Library is support for using the jQuery syntax.  There is so much “good stuff” in the next release for client-side Ajax developers.  I strongly encourage you to check out this PDC video:

Microsoft AJAX Library, jQuery, and Microsoft Visual Studio 2010

If you love jQuery, then you are going to love the next ASP.NET Ajax Library release. You not only get jQuery syntax support, but you get a simplified approach to loading scripts, a rich client-side templating / databinding / “interacting with server data” framework, the ability to instantiate the AJAX Control Toolkit controls easily using client-side code (again using the jQuery syntax), and more.

Here are some essential getting started links:

http://ajax.codeplex.com/

http://www.asp.net/ajaxlibrary/

http://www.asp.net/ajaxlibrary/learn.ashx

http://www.asp.net/ajaxlibrary/apps.ashx

The “learn” link above is the best place to start to wrap your head around all the new capabilities in the upcoming release.  If you want to jump to the jQuery integration, take a look at:

http://www.asp.net/ajaxlibrary/HOW%20TO%20Instantiate%20Controls%20using%20jQuery.ashx

http://www.asp.net/ajaxlibrary/HOW%20TO%20Load%20jQuery.ashx

http://www.asp.net/ajaxlibrary/HOW%20TO%20Use%20the%20Calendar%20Control.ashx

Bottom line…  If you are planning on building an Ajax application, whether you are a .NET developer or not, then you really should check out what’s available in the ASP.NET Ajax Library.  Trust me, you are going to like itSmile.

jQuery & MicrosoftAjax “happy together”

I’ve been using jQuery quite a bit lately.  I’ve grown very fond of it.  At the same time, I have been digging into ASP.NET AJAX 4.0.  I just read a post from Bertand Le Roy that made me smile.  In his post, he shows how you can do the following:

<ul class="dv">

    <li>{{ $dataItem }}</li>

</ul>

<script type="text/javascript">
   1:     $(".dv").dataView({ data: ["foo", "bar", "baz"] });

</script>

To me, being able to instantiate a DataView control using the jQuery plugin syntax is PRETTY COOL!  Check out the details of how all this works and download the sample at:

http://weblogs.asp.net/bleroy/archive/2009/05/04/creating-jquery-plug-ins-from-microsoftajax-components.aspx