This blog post will show you a quick way to get the name of the user using JavaScript.
Where you might use this functionality
This functionality is useful because you might need to update a User lookup field to a particular user in situations like
The current user changed a key field
The current user is primary contact for a project, account, deliverable.
Set a text field of the users name for reporting purposes.
Why are you mentioning it
To do retrieve the current user name in CRM 2011 it took a soap call to retrieve the user name field using the Xrm.Page.context.getUserId(). Below is a blog post I wrote
The Hosk CRM developer mantra is to always start with the CRM SDK to see what methods and functionality exists which can help.
Searching the CRM SDK first helps you see what functionality Microsoft have added, most CRM developers will be surprised the number of new methods added.
It’s very easy for developers to copy and paste existing code in projects but just because it works it doesn’t mean its the best code to use.
This is classic case, the CRM 2011 code is long and involves a soap call, the new functionality added in CRM 2013 allows you to access the data with one line.
Returns an array of strings that represent the GUID values of each of the security roles that the user is associated with or any teams that the user is associated with.
Xrm.Page.context.getUserId()
This would get you the SystemUser.Id
Xrm.Page.context.getUserName();
This would return a text string of the user name
Setting User lookups
The common reason for retrieving the user name and the user id is because both values are needed if you want to programatically set a lookup field in CRM.
Example code is shown below
var setUservalue = new Array();
setUservalue[0] = new Object();
setUservalue[0].id = Xrm.Page.context.getUserId();
setUservalue[0].entityType = 'systemuser';
setUservalue[0].name = Xrm.Page.context.getUserName();
Xrm.Page.getAttribute("LookupField").setValue(setUservalue)
Alternatives
In the requirement I was working on I used JavaScript because I needed to set a field dynamically and instantly. Other CRM customizations may have different requirements and you could set the lookup field using a Plugin or a workflow.
What I have learnt
Use the CRM SDK to see what functionality exists, there might be a better way
Microsoft added a new getUserName method in CRM 2013
You need the guid, name and entity type to set the value of a lookup field
If you don’t need to set the lookup instantly you can use workflows or plugins
CRM forum posts provide extremely useful information from a number of CRM developers
Microsoft have been doing lots of tinkering how the CRM forms are rendered. This graphic shows the effect
// // // // // //
When I saw the graph above my first thoughts were
WOW, Awesome
How did they get such a dramatic improvement
Will this break my customizations
How did Microsoft Improve loading times
I will quote the article
There are 2 main changes that have been made: loading process of the form, and handling of cache.
The article indicates they have moved to parallel loading and are caching more data.
Hmmmm Parallel Javascript loading
The increased form loading is great but parallel loading can have some downsides. I first came across Javascript parallel loading in CRM 2011 rollup 12, you can read about here
To speed up form loading in CRM 2011 they switched to parallel loading and the result meant lots of Javascript methods suddenly stopped working. The reason for this was because one Javascript file was calling a method on another javascript file. This worked when the Javascript files were loaded in an order but when you load them all at once sometimes one Javascript file tries to call another dependant Javascript file which is still loading.
So suddenly lots of Javascript errors appeared and all developers had to write a Javascript wait file, like CRM MVP Scott Durow talks about in this article
This is a significant change and could cause lots of errors if you have Javascript code in your OnLoad functions which call other Javascript files.
As a performance optimization, Microsoft Dynamics CRM forms load JavaScript web resources asynchronously and in parallel. This means that the order in which the libraries are configured for a form does not guarantee that a library will be fully downloaded and initialized before another library might attempt to use one of the objects defined in it.
If you have code that depends on another library to be fully downloaded and initialized, the most straightforward approach is to combine both libraries within a single JavaScript web resource with your code below the library code. A more sophisticated approach is to use libraries such as head.js or require.js to control how the separate libraries are loaded.
Replicants are like any other machine. They’re either a benefit or a hazard. If they’re a benefit, it’s not my problem.
Upgrading to CRM 2015 SP1 could cause big problems to Javascript customizations. It’s good practise to split up your Javascript code to separate files to make it reusable and maintainable but now Microsoft are recommending we put everything in one file. This could turn out to be one big massive Javascript file, which is ok for performance but maintaining and working with this file is difficult.
This change could catch many CRM developers out because the errors are intermittent, sometimes the javascript files will have loaded in the correct order and work.
It will involve developers writing Javascript code which waits until all the Javascript files load which will cancel out any benefits from parallel loading.
It could be seen as an opportunity to restructure Javascript code to have a self contained loading script and then move other Javascript functions to OnChange events. This would be a double win of increased loading time due to parallel loading and running less code.
You can use Legacy form loading style
There is a system setting which contains a global setting to control which form loading style you use.
It’s a great idea for Microsoft to put this in because the new speedier form loading code might take some while getting use to it. When CRM 2011 polaris release came it, it caused a raft of blog posts because CRM Javascript customizations suddenly stopped working.
Settings -> Administration -> System Settings -> General. Select “Yes” under “Use legacy form rendering”
In a perfect world it would have been great to have a entity setting rather than a global setting for the form rendering.
I thought I would write about this because it could effect a lot of people and I never spotted this change until today.
Sometimes when you work on a CRM project which contains lots of Javascript files, it can be difficult to determine what Javascript files are being used and which ones are still needed.
The route cause of this is Microsoft Dynamics CRM forms can have lot of methods triggered from fields or ribbon buttons but these can be difficult to find to find what Javascript files are being used.
Where is Javascript triggered in CRM
Javascript files can be used on CRM forms and the code can be triggered on forms loading/saving or by the OnChange event of a field and the Ribbon buttons. Below is where Javascript files can be used in CRM
Javascript triggered by OnChange events
Javascript triggered by Ribbon buttons
Javascript triggered in form OnLoad/OnSave events
Javascript files used in html pages
There are many different areas Javascript can be used but it can be difficult to see what Javascript files are used and linked to field OnChanges, ribbon buttons.
One of the reasons this is difficult is because the CRM UI means it’s not easy to see what fields have Javascript functions triggered via the OnChange event and the only way is to either look at the Javascript files and hope the CRM Developer has used a logical naming structure.
or
You can click the fields in the CRM form and check if there is an OnChange event.
Javascript development and deployment
Javascript development and Javascript deployment can be a bit disjointed. One method is to write the Javascript file in Visual studio then you copy the Javascript file and paste it into the CRM form changes, save and publish.
It should be noted this isn’t a new problem for CRM 2015/2013 , there have been lots of tools created to help the process.
CRM MVP Mitch Milam created the export Javascript file tool, which I hada used in older versions of Microsoft Dynamics CRM, which you can read about here
The Microsoft Developer toolkit brought big improvements which allowed you to deploy/update Javascript file changes from Visual studio. I go through the process in this video from Hosk CRM Dev Youtube channel
What Javascript files are used
I recently worked on a project which had gone through some optimization and refactoring, my current task is finding out if all the Javascript files are needed for each of the forms.
The reason the project is in this state is we quickly needed to optimize the code and whilst doing this the Javascript was optimized and refactored, this has resulted in some of the Javascript files not being needed
The code was refactored but some of the Javascript files which were no longer used were not removed.
The code was also part of the Async Javascript load issue, which happened in CRM 2011 Rollup 12
Tidy up Javascript files on forms, remove the WaitForScriptsLoaded Javascript file and replace the onload method with the entity Javascript file.
Remove Javascript files which are no longer referenced.
Factors
To make the problem harder, the Javascript was split over 10 different Javascript projects, which made find if Javascript files were used
To help me the project adhere’s to Javascript best practices and uses Javascript namespaces.
link to Javascript namespaces
Things to consider
When looking at what Javascript files are needed don’t forget to check the Javascript files used for the ribbon buttons, in this particular project most forms had 5 custom ribbon buttons.
Tools used
Fiddler
I used Fiddler to track what calls were being made out of the form
Visual Studio
I used Visual studio to look at the Javascript files included on the FORM.
F12 Debugger
Press F12 on a record and I could see all the Javascript files being used.
Script finder tool
I knew there was a script finder tool but I couldn’t find it when searching the internet. Thankfully a reader added a comment and of course it’s in the everyone’s favourite CRM tool or collection of Tools the XRMToolbox.
The XRMToolbox has a Script finder tool which will list all the Javascripts and will show the event e.g. OnLoad, OnSave, OnChange as you can see from the screenshot below
The tool looks great but I would say the project I was working on has a lot of Javascript and when I tried I pressed the find scripts button it never came back. I think it timed out because there are loads (hundreds) of scripts and functions.
Process of finding unused Javascript files
I did try doing a find in files but this proved to be very slow and seemed difficult, I eventually decided this process wasn’t really working.
So I looked at the problem a different way
How do I find what files are used when the CRM form is being used?
I came up with two main methods.
Method 1
Go through the main Javascipt file specified in the form onSave/OnLoad and look what other Javascript files/methods are referred. Thankfully the Javascript files used were developed with using Javascript Namespaces so I could search for the namespaces in the file to see what other Javascript files were used.
I cold then compare the Javascript files listed in the Javascript files for the form and what Javascript files were referenced in those Javascript files.
Method 2
When the Javascript form is being used in CRM you can press F12 to get the debugger up, I could see what Javascript files are loaded.
Why did this happen
Good CRM Development will mean the CRM developer will create lots of seperate Javascript files which can used in multiple CRM forms. The reason you split the Javascript file into common Javascript files is because it’s better to use the same Javsacript code in many different forms rather than copy the code in many different Javascript files (e.g. if you have one Javascript file for each form).
You never want to duplicate code because if there is a bug in the code then you would have to fix all the various copies of the code and the chances are you would forget to change some of them. Later it would be difficult for the CRM developer to know which code was fixed and which code still had the bug in.
When Javascript code is no longer needed CRM developers often forget to remove Javascript files and methods, this can add to the confusion for a CRM developer when there are javascript files and methods which don’t seem to be used. It can be scary to be the CRM developer to remove unused Javascript files and methods because it’s difficult to be 100 percent sure they are not used anywhere.
Javascript is a slippery beast, Slave to no one and master to many. It’s just a quick blog post today, not as quick as this article I found written by me
Good question, surely I should like dynamic things.
Some of the reasons I don’t like it are
Hard to read/understand other peoples code
Bugs can be compiled and then appear in runtime when the code is run
It encourages the cowboy coders to go to town
It’s strange and different
Get to the point
I’m not saying I don’t like Javascript it’s just sometimes I want to do things and I’m not sure HOW because the syntax can be a bit crazy. Like all developers once we have a working example in our hands, we are off. So recently I saw some interesting Javascript in a project I am working and I was intrigued to understand how it worked and use it again.
One cool feature about Javascript is the ability to pass in function names using variables, a bit like reflection(ish), but only once you know how because I tried searching for this on the internet and fell down a big dark hole.
Example
On a form I have 4 OptionSets which we are dynamically setting the values to.
If I pass in the OptionSetField name I can dynamically get the control
var control = Xrm .Page .getControl (OptionSetFieldName);
I can then clear this control
control. clearOptions();
I can then add in the new values and build it up. The beauty of dynamic code is I can use the same code for all the OptionSets because I can pass in the name of the control.
When adding a the newoptionSetvalues in, I can use a dynamic variable to retrieve the field name from array, which contains values retrieved from a fetchXML query. The childField is the name of the field in CRM.
It may be common knowledge to all you JavaScript wizards out there, but I hadn’t used or seen JavaScript using dynamic names. It makes sense and it’s very useful so I thought I would share it with you
I was reading this today and I noticed it had a Javascript Programming Best Practices section. Javascript is very useful but I often feel the code produced in Javascript is not alway the best quality because there is no type checking and the process of writing the code and uploading is a bit of a hassle.
I have selected a couple of the best Practices but to read the full list go to the article
Microsoft have also created best practices for different versions, links to below to the different pages
There are a lot of best practices and it’s a really good article, but below are my top 4 best practices from the article. I would definitely recommend you read the different articles.
Use a Cross-browser JavaScript Library for HTML Web Resource User Interfaces
A cross-browser JavaScript library, such as jQuery, provides many advantages when developing HTML web resources that must support multiple browsers. JavaScript libraries like jQuery provide a unified development experience for all browsers supported by Microsoft Dynamics CRM. These capabilities are most appropriate when you are using HTML web resources to provide user interfaces. JavaScript libraries like jQuery provide consistent ways to interact with the Document Object Model (DOM).
Use Feature Detection When Writing Functions for Multiple Browsers
Even when you use a cross-browser library like jQuery, you need to be very aware of differences between browsers. You can generally detect which browser is being used by querying thenavigator.useragent property. This is called browser detection. Browser detection is not a good strategy for most cases because it can’t take into account what features newer versions of a browser have. Also, some browsers provide the capability to modify the navigation.useragent property so that they appear to be a different browser.
Feature detection is the recommended approach. By detecting what features are available, you can create code paths for the browsers you support without knowing exactly which browser is being used. For more information about feature detection, see How to Detect Features Instead of Browsers.
Define Unique Names for Your JavaScript Functions
When you are the only developer for an HTML page you can easily manage the names of the JavaScript functions you use. In Microsoft Dynamics CRM, other solutions may add JavaScript functions to the page where your function is used.
If two JavaScript functions on a page have the same name, the first function defined is overwritten by the second. For this reason, make sure that you define unique names for your JavaScript functions. For more information, see Creating Script Libraries.
Use Asynchronous Data Access Methods
When you access data by using the Microsoft Dynamics CRM web services that use the REST or SOAP endpoint for web resources, always use an XMLHttpRequest that is configured to execute asynchronously. The reason is that the browser operates on a single thread. If that thread is being used to execute a long-running process synchronously the browser will stop responding.
I had written some javascript which retrieved values from a field which I was displaying on the form.
I had added an account field onto a quote product, so I could then use the account id to inject into some fetchXML in a subgrid so I only showed quote products which had only been sold to the the account selected on the quote.
I could have looked this up using a query but I thought I would add it onto the Quote Product form and pass the value using relationships.
It worked fine but as I came to release the code I thought I didn’t really need the account lookup field on the form so I took it off.
Then when testing my code it wasn’t working, so I pressed F12 and was ready to debug, except it wasn’t running my code because it was erroring whilst trying to get the account lookup field, with this error.
SCRIPT5007: Unable to get value of the property ‘getValue’: object is null or undefined
So the morale of the story is, you can only access fields in Javascript which are on the form. The solution to this problem was to make the fields not visible.
This is logical when I stop to think about it because why would CRM load up all the variables which are not being used on the form, it would be a complete waste of time.
This was an early morning, not fully awake error but it does show you the danger of taking off variables from a form without seeing if any javascript uses those fields for something
A quick blog entry and a suprisingly easy and small piece of code
In the code below I have function which gets triggered when a user ticks the confirm Closed checkbox it then sets the current date and time.
if the user untick the checkbox I wipe the date and time value.
The date functionality in javascript holds the current time as well
function confirmClosedOnChange() {
var closedConfirmed = Xrm.Page.getAttribute("new_closedconfirmed").getValue()
if (closedConfirmed) {
var currentDateTime = new Date();
Xrm.Page.getAttribute("new_confirmedcloseddate").setValue(currentDateTime);
} else {
Xrm.Page.getAttribute("new_confirmedcloseddate").setValue(null);
}
}
A quick blog post to point you in the direction of a couple of exellent tools to display images in for a contact (or other entities).
The timing of this was a day too late (for me) because I had written a basic way to display images yesterday and then today I find the solution today and it works better than mine because you can have multiple images and it resizes the images in a neat way, working out the aspect ratio from the available space.
Both solutions use the method of uploading picture files as a note for the contact and then display these.
For the html, jquery method then go to this blog and you can download the solution file
You will need to add the image img_browser.html as a webresource onto your page. This is very useful because I think (I haven’t tried it) use this to display images on other entities.
The MSCRM blogger team have also created a silverlight version, well actually they created that first, you can get that here
I had a requirement this week where a customer was adding products to a quote and when they selected a product they then want to see previous quotes which featured the same product and the price and quantity it sold for. Basically the sales person wanted to see what the product had been sold for before to make sure the price they were quoting wasn’t too radical.
The idea I came up with was to have a grid on the Quote Product form, which displayed quote products of the same type as the quote product selected.
This would mean I would have to dynamically change a view or show items in the grid.
I created a view showing the fields of the Quote Product and then specified a product I was searching for.
This blog post explains how you can load in new fetchXML into a subgrid, you can inject the FetchXML on the form onload, which enables you to get some variables from the form and inject them into FetchXML which then is used to update the SubGrid.
So on my Quote Product form I checked to see if a product had been selected on the form OnLoad, on this particular form the subgrid doesn’t load until you have selected a product, unit and a quantity, which then reloads the form.
The code itself which I have taken and changed from the blog post referenced above, is quite clever. The function is called and if the SubGrid has not been loaded, it calls the function again after a small time delay. This ensures the SubGrid is loaded before you try and inject the fetchXML into the view.
The FetchXML is created, I got the fetchXML by doing an advanced find on my previously created view, there is a button which allows you to retrieve the FetchXM, which is very useful.
function UpdateSubGrid() {
var quoteGrid = document.getElementById("Quote_Products");
var productId = Xrm.Page.getAttribute("productid").getValue();
if (productId != null){
//If this method is called from the form OnLoad, make sure that the grid is loaded before proceeding
if (quoteGrid == null) {
//The subgrid hasn't loaded, wait 1 second and then try again
setTimeout('UpdateSubGrid()', 1000);
return;
}
var fetchXml = ""
+ " <entity name='quotedetail'>"
+ " <attribute name='productid' />"
+ " <attribute name='productdescription' />"
+ " <attribute name='priceperunit' />"
+ " <attribute name='quantity' />"
+ " <attribute name='extendedamount' />"
+ " <attribute name='salesrepid' />"
+ " <attribute name='uomid' />"
+ " <attribute name='manualdiscountamount' />"
+ " <attribute name='baseamount' />"
+ " <attribute name='new_quoteid' />"
+ " <attribute name='quotedetailid' />"
+ " <order attribute='productid' descending='false' />"
+ " <filter type='and'>"
+ " <condition attribute='productid' operator='eq' uiname='1 Function Easy Clean Mini Kit' "
+ " uitype='product' value='" + productId[0].id +"' />"
+ " </filter>"
+ " <link-entity name='quote' from='quoteid' to='quoteid' visible='true' link-type='outer' alias='a_ff5a49bd001a45f7a14dd99a28f37f91'>"
+ " <attribute name='customerid' />"
+ " <attribute name='name' />"
+ " <attribute name='quotenumber' />"
+ " <attribute name='quoteid' />"
+ " </link-entity>"
+ " <link-entity name='product' from='productid' to='productid' visible='false' link-type='outer' alias='a_e0b689bded554f07ab0b241a932d482e'>"
+ " <attribute name='productnumber' />"
+ " </link-entity>"
+ " </entity>"
+ "</fetch>";
// alert(fetchXml);
//Inject the new fetchXml
quoteGrid.control.setParameter("fetchXml", fetchXml);
//Force the subgrid to refresh
quoteGrid.control.refresh();
}