Skip to main content

Posts

Showing posts from 2010

ForceSubmit and Default Read-Only Lookups

I made quite the discovery the other day with the ForceSubmit property.  I was writing a plugin on pre-create of an entity where I needed to grab a lookup attribute from the entity being created.  I finished the plugin and then tried testing it out.

I went to create a new record for this entity and realized that the lookup I needed to populate was set to read-only in the form customizations.  I used the IE8 dev tool bar to execute some javascript that enabled the lookup and then set the ForceSubmit property to true so it would save the value.  I then populated the lookup and created the record.

I was greeted with this infamous error:
My first instinct was that my plugin wasn't working correctly, so I set a breakpoint but it wasn't getting triggered.  I then created a record without populating this lookup and it hit my breakpoint and worked successfully.  My next thought was that maybe ForceSubmit was the culprit.  To test this theory I enabled this lookup in the form customiza…

Show Column Total from a CRM Grid

Update: Andriy a33ik Butenko pointed out that my solution won't work on all views because the specific column will probably not be in all of the views. I updated the solution to check if the column exists first, if not it will prompt the user that this functionality can't be done on the selected view.

A user on the CRM forums asked if it was possible to be able to show a column total from highlighted records in a CRM grid. I went ahead and wrote some javascript to implement this functionality. The javascript for this is fairly simple and will be executed from a button in the ISV Config for an entity grid. I will be using the native Opportunity grid and I will be calculating the Est. Revenue column from that grid.

First, we can't do this functionality if our column doesn't exist in the view, so we will create a function to check if our column exists (estimatedvalue in this case).  We will first create a function called 'doesColumnExist':

function doesColumnExist…

ForceSubmit Property

There are a lot of scenarios where you need to automatically populate a field when it is read-only or will be set read-only dynamically.  In this scenario you would want the value to be saved when the user clicks Save, but by default a field that is read-only will not submit.  To get a read-only field to submit, you can set the ForceSubmit property of the field to true using javascript:

crmForm.all.name.ForceSubmit = true;
What ForceSubmit actually does is always submit that attribute to be saved, whether or not it was actually modified on the form.  One thing to note is that if you have a plugin that is filtering on an attribute where ForceSubmit is set to true, then your plugin will always be triggered when the user saves the form.  Also if you set ForceSubmit to true on ownerid then it will always execute an Assign message whether or not the owner was actually changed.
Because of the way ForceSubmit works, the best way to use it would be to only set it if the field was actually chang…

Simple CRM Tools

A colleague of mine recently turned me onto some very useful tools that are simple and easy use. Often times as a CRM developer, we find ourselves needing either the entity type code or the GUID of the record we’re on.  We can easily obtain this information by creating a bookmark that displays either the GUID or the entity type code, directly from the form we’re on.  As an added benefit, we can also set the values to our clipboard so they can be pasted as needed.

To create these bookmarks, just browse to any CRM page and add it to your favorites.  Then, you can edit the bookmark and set the URL to the javascript you would like executed.


Here's the javascript to do so:


Entity Type Code:
javascript:if (crmForm.ObjectTypeCode){clipboardData.setData("Text", crmForm.ObjectTypeCode.toString()); alert(crmForm.ObjectTypeCode);}
Entity ID:
javascript:if (crmForm.ObjectId){clipboardData.setData("Text", crmForm.ObjectId.toString()); alert(crmForm.ObjectId);} else { alert('…

SharedVariables

I came across a good MSDN article about a plugin feature that I personally think most people overlook.  That feature is SharedVariables.  It is a way to pass data from the pre event to the post event in your plugin so that your post event plugin can use the data as needed.  It is probably very rare that you would ever need to use this functionality (I've only used it once out of the dozens upon dozens of plugins I've developed) but it is good to know it exists.

http://msdn.microsoft.com/en-us/library/cc151094.aspx

ActivityParty Property Con't

Last month I made a post about grabbing an ActivityParty property from a DynamicEntity and recently someone on the CRM forums made a post asking how to add an ActivityParty property to a DynamicEntity.  This can be very confusing and not straightforward at all so I'm going to post the snippet that I answered with in hopes to help some people out.

            DynamicEntity email = new DynamicEntity("email");
            // setup email attributes

            DynamicEntity contactParty = new DynamicEntity("activityparty");
            contactParty.Properties.Add(new LookupProperty("partyid", new Lookup("contact", new Guid("Contact ID"))));

            email.Properties.Add(new DynamicEntityArrayProperty("to", new DynamicEntity[] { contactParty}));

Note:  Shan McArthur replied to the post on the forum saying that this becomes easier with the new XRM dlls from the latest SDK.  Hopefully I can play around with these new dlls soo…

Changing a Form Field Label

A question was posted in the CRM Forums on how to change a form field's label using javascript onload.  One thing people might not consider is that if you just change the innerText of the field label and the field is required then you will override the asterisk image that is next to the label.

To change the field label correctly, we will need to find the label element and change it's text to our new label rather than overriding the innerText.  Below is an image of the DOM of a field label in Dev Toolbar where I'm highlighting the text that we are going to find and change.



Here's the script to do so:

function changeFieldLabel(fieldName, newLabel)
{
     var field = crmForm.all[fieldName + "_c"];
     if (field != null)
          crmForm.all[fieldName + "_c"].firstChild.firstChild.nodeValue = newLabel;
}

Which you can use like so:
changeFieldLabel("name", "New Name");

Querying N:N Relationships

Native N:N Relationships are not considered Entities in CRM 4, therefore the web services will not support using a RetrieveRequest against the N:N table.  However it is possible to query the table using Fetch XML.  Below is a simple Fetch query to retrieve the records in the "systemuserroles" N:N table.



"resultXml" would look something like this:




and now you can parse through the result to grab the data you need.

Delete Plugin "Gotcha"

Today I discovered a nice "gotcha" moment when trying to delete a custom entity record.  This is the error I was seeing:


After trying to use a debugger to step into the delete plugin and failing miserably, I finally discovered that the plugin had an image that was not being used.  Once I removed the image and re-registered the plugin, it triggered successfully. 
Further testing revealed that anytime you register a post image with a delete plugin then your plugin will not even trigger and throw the error shown above.  This makes complete sense because the record will not have a post image as it will be deleted.

ActivityParty Property

The Properties of a DynamicEntity can be confusing at first but are pretty straightforward after you get the hang of it.  However, one property that can be hard to figure out is the ActivityParty.  It is actually an array of DynamicEntity and each DynamicEntity in that array has a Lookup property called "partyid".  Here's a code snippet for retrieving the "to" from an activity DynamicEntity in a plugin.

Note:  This snippet is just finding the first record in the To attribute.

DynamicEntity activity = (DynamicEntity)context.InputParameters.Properties["Target"];
if (activity.Properties.Contains("to"))
{
     DynamicEntity[] to = (DynamicEntity[])activity.Properties["to"];
     if (to.Count() > 0 && to[0].Properties.Contains("partyid"))
     {
          Lookup partyId = (Lookup)to[0].Properties["partyid"];
          // Run logic
     }
}

Offline IFrames

Not all of your functionality will be possible in CRM Offline mode.  For example you may have some IFrames that require an internet connection.  For these scenarios you would not want to have the browser display an error to the user.  Just hiding the IFrame may not be sufficient enough either as it may confuse your users as to why it disappeared.  A nice solution in this case is to hide the IFrame as well as provide the user with a reason as to why they can't see it.

Here's a function to hide the IFrame and overlay it with div containing a custom message explaining why the user cannot see the IFrame.

function ReplaceOfflineIFrameWithMessage(iFrame, messageText)
{
if (iFrame)
    {
        iFrame.style.display = "none";

var messageDiv = document.createElement("div");
        messageDiv.innerText = messageText;
        messageDiv.textAlign = "center";
        messageDiv.style.fontSize = "12px";
        messageDiv.style.color = "red";

How to Prevent Closing an Opportunity

If you ever need to execute some logic when a user clicks "Close Opportunity" from the Opportunity form, then a good technique is to wrap CRM's native close javascript function with some custom javascript.

The following javascript should be ran onload of the form.

First we will declare our function that will return a boolean based on whether the user can close the Opportunity or not.

canCloseOpp = function() { var canClose = false; // validate if you can close the opp or notreturn canClose; } Then we find the "Close Opportunity" button by id and if it exists we will change the action property which will get executed when the user clicks the button. We will first call our custom function to see if the user can close the opportunity. If it returns true we will call "complete" which is CRM's native function to close an opportunity. If it returns false we will display an alert explaining why the Opportunity can't be closed. var b…

CRM Pop-ups

Working with CRM day in and day out, you will find that sometimes all the pop-ups can get on your nerves.  I offered a solution to someone on the CRM forums on how to change the way IE works to open pop-ups in a new tab (Which was also blogged about by Jim Glass).

Tools -> Options -> In the tab section, click Settings -> Open pop ups in a new tab

Note:  On a form, custom iframes will be noticeably larger in a full tab than in a pop-up, so expect this to look quite different. Most users will likely keep their IE settings default, so keep this in consideration when developing custom iframes.