Category: Javascript

{Bookmarklet} Refresh Form Data

{Bookmarklet} Refresh Form Data

Recently I was developing a plugin in which, whenever a record updated some of the fields were updated and for reflecting those fields I need to refresh the page. I was tired to refresh the page again and again.so I come up with a solution that would also increase productivity.

I made a small bookmarklet that will help me to refresh form data without refreshing the entire page.

Here is code

javascript: (function () { debugger;(document.querySelectorAll(‘iframe’)).forEach(function (frame, v) { if (frame.style.visibility !== ‘hidden’) { if (frame) { var Xrm = frame.contentWindow.Xrm; Xrm.Page.data.refresh(); alert(‘Form Data Refreshed…’) } else { alert(‘Entity form not detected’); } } }) })();

Note: Before using the above code please update single quotation mark.

For adding this bookmarklet on chrome , refer below link

https://crmdynamicsblog.wordpress.com/2016/06/10/bookmarklet-get-current-record-guid-from-crm-form/

Hope it’ll help someone.

 

Add custom fetch XML to subgrid lookup

Add custom fetch XML to subgrid lookup

In this blog, I am going to show how we can change subgrid lookup behavior. Basically, I want to control custom N:N contact subgrid lookup, depend on company lookup that is on the contact form.

e.g. A.Datum company have five contacts and if I select contact lookup (custom N:N subgrid inline lookup ) on one of contact form so it’ll only show four contacts in subgrid lookup excluding this contact.

I have an N:N subgrid and company lookup on the contact form.

2

What’s the tricky part for getting subgrid lookup ?

Inspecting DOM

For add event on subgrid lookup, we need to inspect the DOM for subgrid and look out for lookup object.

Have a look below image, It clearly shows how we can find lookup , object by object.(if object key, not the same like below then find lookup with help of object name.)

FYI I am using Dynamics 365 online.

3

After inspecting the DOM structure of the subgrid and carefully understand the mechanics of the lookup filter,we can set filter criteria like in the JavaScript below:

 var RelatedContact = Xrm.Page.getControl('RelatedContact');
 var RelatedContactLookup = RelatedContact.$0_3.$1m_4.$O_4.$38_3.$3_6;
 RelatedContactLookup.addPreSearch(function ()
 {
 if (Xrm.Page.getAttribute("parentcustomerid").getValue())
 {
 var parentCustomer = Xrm.Page.getAttribute("parentcustomerid").getValue()[0].id;
 var strVar = "";
 strVar += "<filter type=\"and\" >";
 strVar +=" <condition attribute=\"statecode\" operator=\"eq\" value=\"0\" />"
 strVar += " <condition attribute=\"parentcustomerid\" 
               operator=\"eq\" value=\"" + parentCustomer + "\" \/>";
 strVar += " <\/filter>";
 strVar += "";
 RelatedContactLookup.addCustomFilter(strVar, "contact");
 }
 })

 

Get the company id from Xrm.Page library  and passes in fetchXML for search criteria.

Our filter criteria code is done but for triggering the above code, we need to attach click function to the subgrid add button, like in JavaScript below :

var RelatedContact_Button = window.parent.document.getElementById("RelatedContact_addImageButton");
 RelatedContact_Button.addEventListener("click", function ()
 {
 ///put your filter code here  
 }

Here is complete code for JavaScript web resource that we need to add on a contact form.

You can also write this code inside a function and call it onload, here I am using self invoking JS function.

(function ()
{
 setTimeout(function ()
 {
 var RelatedContact_Button = window.parent.document.getElementById("RelatedContact_addImageButton");
 RelatedContact_Button.addEventListener("click", function ()
 {
 var RelatedContact = Xrm.Page.getControl('RelatedContact');
 var RelatedContactLookup = RelatedContact.$0_3.$1m_4.$O_4.$38_3.$3_6;
 RelatedContactLookup.addPreSearch(function ()
 {
 if (Xrm.Page.getAttribute("parentcustomerid").getValue())
 {
 var parentCustomer = Xrm.Page.getAttribute("parentcustomerid").getValue()[0].id;
 var strVar = "";
 strVar += "<filter type=\"and\" >";
 strVar += " <condition attribute=\"parentcustomerid\" operator=\"eq\" value=\"" + parentCustomer + "\" \/>";
 strVar += " <\/filter>";
 strVar += "";
 RelatedContactLookup.addCustomFilter(strVar, "contact");
 }
 })
 })
 }, 2000)
}())

You can also download from here.

animation

 

That’s it , Please try and comment below If you found any problem.

Hope it’ll help someone.

 

Note: This is an unsupported way if you really want to go with a supported way then use custom web resource HTML for showing your grid with filter criteria.

Multiple views inside a tab on CRM dashboard

Multiple views inside a tab on CRM dashboard

In this blog, we’re going to implement multiple views inside a tab with the help of web resource.

we are showing Active Accounts, Active Contacts, and Open Opportunities views into a tab of a dashboard.

for this, I used Javascript Tabifier library, you can download JS and CSS from below link

Javascript Tabifier library

let’s upload and publish Tabbler.js and their CSS on our CRM Organization.we can use XrmToolbox for maintaining CRM web resources.

create a new HTML web resource i.e. MultiViews. Inside this, we’ll write our code for showing three different views in a web resource.

crmweb.PNG

For showing views in Iframe we need views URL’s.For more info about how to get URL please refer below link

Copy the URL for a View

email

Here is code for HTML page

<!DOCTYPE html>

<html lang=”en” xmlns=”http://www.w3.org/1999/xhtml”&gt;
<head>
<meta charset=”utf-8″ />
<title></title>
http://../../ClientGlobalContext.js.aspx
http://../content_/js/tabber_minimized.js
<link rel=”stylesheet” href=”../content_/css/example.css” type=”text/css” media=”screen”>

/* Optional: Temporarily hide the “tabber” class so it does not “flash”
on the page as plain HTML. After tabber runs, the class is changed
to “tabberlive” and it will appear. */

document.write(‘.tabber{display:none;}’);

</head>
<body>

Note: Iframe tag is not supported as a text in WordPress so please download the source code from here

In the above code, we’re using Active Accounts, Active Contacts, and Open Opportunities views URL.Now let just add this web resource on dashboard or use a web resource whatever.

m1.PNG

tabbler

That’s it . Now we can see multiple views inside a single web resource.

Here is the link for source code

https://1drv.ms/f/s!AvWbcg6Nl97LiU1kl6GQg1snKfgr

Thanks for visiting my blog.

{Bookmarklet} Get current record Guid from CRM form

{Bookmarklet} Get current record Guid from CRM form

Most of the time when we developed some new functionality in crm, we need current entity record GUID for debugging and checking our modification using advanced find , Odata query etc.

In this blog I am going to create a simple bookmarklet for getting current enity record GUID.

What is Bookmarklet?

A small software application stored as a bookmark in a web browser, which typically allows a user to interact with the currently loaded web page in some way.

(definition from google)

For more details on bookmarklet creation refer below link

http://code.tutsplus.com/tutorials/create-bookmarklets-the-right-way–net-18154

Let’s write a JavaScript code that we use for our bookmarklet.

javascript;
(function () {
(document.querySelectorAll(‘iframe’)).forEach(function (frame, v) {
if (frame.style.visibility !== ‘hidden’) {
if (frame) {
var Xrm = frame.contentWindow.Xrm;
prompt(“Copy GUID for the current record”, Xrm.Page.data.entity.getId());
} else {
alert(‘Entity form not detected’);
}

}
})
})();

Now add a new page on chrome from bookmark bar

2

In name give some meaning name like ‘GETID’ and in URL paste our JavaScript code

1

Now try this on Entity Form, we’ll get the GUID of current record.

GIF

 

That’s it. Hope it’ll help someone 🙂

Thanks for visiting my blog!!!

 

 

 

 

Angular Interceptor for Converting UTC date time into Local date time

Angular Interceptor for Converting UTC date time into Local date time

Hi Everyone recently I have a requirement in which we have to convert every date time attributes of  AJAX response into local date time because response date time attributes in UTC but we wanted in local date time.

It is always good to save all our date time information into UTC format on server because using of UTC format we can calculate local date time easily with just knowing user timezone.

E.g. In our database we saved date in UTC format that is 2016-05-29 00:00:00(UTC) but we want to show this according to user timezone like for India timezone user that is 2016-05-29 05:30:00(GMT+5:30).

For achieving this I wrote a angular interceptor that runs on every AJAX request and check every AJAX response that have a valid date time attributes then converted  into local.

Let’s start with creating a new angular factory and use into our app.js config section.

1.Add a new JavaScript namespace that contains important function

//Namespace
var dateUTC = {};
dateUTC.checkNested = function (prop, val1) {
//check for string
if (typeof (val1[prop]) == “string”) {
if (isNaN(val1[prop])) {
if (dateUTC.checkISOdate(val1[prop])) {
val1[prop] = moment(moment.utc(val1[prop]).toDate()).format();
}
}
}
//check for object
if (typeof (val1[prop]) == “object”) {
//start loop for array
for (var prp in val1[prop]) {
if (typeof (val1[prop][prp]) == “string”) {
if (dateUTC.checkISOdate(val1[prop][prp])) {
val1[prop][prp] = moment(moment.utc(val1[prop][prp]).toDate()).format();
}
}
if (typeof (val1[prop][prp]) == “object”) {
//start loop for nested object
for (var pr in val1[prop][prp]) {
if (typeof (val1[prop][prp][pr]) == “string”) {
if (isNaN(val1[prop][prp][pr])) {
if (dateUTC.checkISOdate(val1[prop][prp][pr])) {
val1[prop][prp][pr] = moment(moment.utc(val1[prop][prp][pr]).toDate()).format();
}
}
}
if (typeof (val1[prop][prp][pr]) == “object”) {
for (var p in val1[prop][prp][pr]) {
dateUTC.checkNested(p, val1[prop][prp][pr]);
}
}
}
}
}
}
};
dateUTC.checkISOdate = function (date) {
if (moment(date, “YYYY-MM-DDTHH:mm:ss.SSS”, true).isValid()
|| moment(date, “YYYY-MM-DDTHH:mm:ss.SS”, true).isValid()
|| moment(date, “YYYY-MM-DDTHH:mm:ss.S”, true).isValid()
|| moment(date, “YYYY-MM-DDTHH:mm:ss”, true).isValid()) {
return true;
}
return false;
}

2.Create a new factory that intercept on every AJAX request

Myservice.factory(‘dateinterceptor’, function () {
return {
request: function (config) {
return config;
},

requestError: function (config) {
return config;
},

response: function (res) {
if (typeof (res.data) == “object”) {
if (res.data) {
if (res.data.length) {
angular.forEach(res.data, function (val, key) {
if (typeof (val) == “object”) {
if (val) {
if (val.length) {
angular.forEach(val, function (val1, key1) {
for (var prop in val1) {
dateUTC.checkNested(prop, val1);
}
})
}
else {
for (var prop in val) {
dateUTC.checkNested(prop, val);
}
}
}
}
})
}
else {
for (var prop in res.data) {
dateUTC.checkNested(prop, res.data);
}
}
}
}
return res;
},

responseError: function (res) {
return res;
},

}
});

3.Add our date interceptor factory appModule.config section

appModule.config([‘$httpProvider’, function ( $httpProvider) {
$httpProvider.interceptors.push(‘dateintercepter’);
}]);

Thanks for vising my blog.

Hope it’ll help someone.

 

 

MS CRM dynamics with Firebase(using JS)

MS CRM dynamics with Firebase(using JS)

Real-time applications provide so much functionality across so many different types of applications. There’s Google Drive real-time editing, Twitter showing new tweets and so many more.

It’s always good to learn how to make these types of techniques by learning things like socket.io

Today I am going to tell how we can use firebase with MS dynamics CRM and make real time notification model for mobile\web users.

Like status Change ,Create ,Update or some other useful requests that we performed in CRM , we can easily integrate Firebase in all that condition and Sync important data with users .

What is Firebase?

Firebase is an API service to store and sync data in real-time. What this means is that you don’t have to worry about the backend server, database, or real-time component (socket.io). All of that is handled for you by Firebase.

Just grab data from Firebase, save data to Firebase, and Firebase will worry about saving, and also syncing across all connected devices/sites. Piece of cake!

firebase

Let’s integrate firebase in CRM  !!

Before writing any code first we need to make firebase API.

AppName

After successful creating of App we get one URL like https://XXXXXX.firebaseio.com 

For more info about firebase configuration and security Please refer this link

https://www.firebase.com/docs/

What we want is to receive notifications whenever the status of case records changed.

We are using https://mscrmdynamics.firebaseio.com/Cases AppUrl for all firebase operation.For demo you can also use it.

Let write some client side code(JS) on Save Event of Case Form.

Make new Web resource type Jscript and inside it write the code which communicate with firebase on Save Event of case form.

1

In above code I used RequireJs for Injecting Firebase and underscore Scripts. we can also use downloaded files and add them in form.

Whenever status changed we send a json body with Incident(case) attributes like Incident Id, Title, Status ,Owner to Firebase and save it.

We check all case (https://xxxxxx.firebaseio.com/Cases) snapshots on our Apps that sync with our system or mobile Phones. After getting data we made our logic for showing information through notifications.

OK let’s move to the next step, we’ll call the function when record updated with Event mode value  1 or 2 or 70.

For more Information about Save Event Argument please refer Below link

https://msdn.microsoft.com/en-us/library/gg509060.aspx

Before adding/creating new case, we need to check the existance of that case in firebase that this case is not already present and if it exist then we need to update it’s status only.

2.PNG

That’s it. Now we can Sync Case record status with firebase and we can use it’s data for many purposes of sales/services/marketing.

Lets save case with status On Hold .That reflects in firebase, show in below screens

4

5

On changing status of case, it’ll immediately reflects in firebase.

6

7

Here is the link for complete code and video.

http://1drv.ms/1UpKKXo

 

Thanks for visting my blog.

Do some creative stuff in CRM  !!!  🙂

 

 

Add Form Library on CRM Form using C# or javascript

Add Form Library on CRM Form using C# or javascript

Hello Everyone, Today I am going to tell how we can add form library on CRM form using C# or  JavaScript.

We want to add library on account form so for that I created one JavaScript web resources e.g.  am_sample for our demo purpose or you can add existing JS from CRM.

2

After that we add alert functionality inside this so we’ll found ourselves that our code is executed on onload of account form. We put our code inside self invoking function so it will show alert dialog on load of account form.(By using self invoking function we don’t need to define any function in Event Handlers)

here is demo link for self invoking function in JavaScript.

http://embed.plnkr.co/TSEL09/

1

3

In below screen we don’t see any library added on account form let’s write some code for adding file here 🙂

4

 

C# Code :

First we add one function for get form xml in which we passes logical name of Account entity as its parameter.

 

public Entity GetForm(string EntityLogicalname)
{
try
{
QueryExpression query = new QueryExpression(“systemform”)
{
Distinct = false,
ColumnSet = new ColumnSet(new[] { “name”, “formxml”, “objecttypecode” }),
Criteria =
{
Filters =
{
new FilterExpression
{
FilterOperator = LogicalOperator.And,
Conditions =
{
new ConditionExpression(“objecttypecode”, ConditionOperator.Equal, EntityLogicalname),
new ConditionExpression(“type”, ConditionOperator.Equal, 2),
new ConditionExpression(“iscustomizable”, ConditionOperator.Equal, true),
new ConditionExpression(“formactivationstate”, ConditionOperator.Equal, 1)
}
}
}
}
};
return Service.RetrieveMultiple(query).Entities.FirstOrDefault();
}
catch (Exception)
{
throw;
}
}

This function return Entity with formxml attribute.

After that we need to add one more function that change current formxml of Account entity (which return from above function) with new JS that we need to add.

Below is the description of what we’re going to perform in our next funtion :

  • First we select Form node, and formLibraries inside it.
  • If formLibraries not found then we’ll create formLibraries xml node.
  • If formLibraries found then we’ll create Library element inside it with name, libraryUniqueId attributes.
  • After that we append this Library tag into formLibraries and update formxml attribute of Entity.

 

public void AddLibrary(Entity form, string libraryName, bool addFirst)
{
var formXml = form.GetAttributeValue<string>(“formxml”);
var formDoc = new XmlDocument();
formDoc.LoadXml(formXml);
var formNode = formDoc.SelectSingleNode(“form”);
if (formNode == null)
{
throw new Exception(“Expected node \”formNode\” was not found”);
}
var formLibrariesNode = formNode.SelectSingleNode(“formLibraries”);
var eventLibrary = formNode.SelectSingleNode(“events”);
if (formLibrariesNode == null)
{
formLibrariesNode = formDoc.CreateElement(“formLibraries”);
formNode.AppendChild(formLibrariesNode);
}
if(libraryName!=null)
{
var libraryNode = formLibrariesNode.SelectSingleNode(string.Format(“Library[@name='{0}’]”, libraryName));
if (libraryNode != null)
{
Console.WriteLine(“This library is already included in this form”);
}
var nameAttribute = formDoc.CreateAttribute(“name”);
var libraryUniqueIdAttribute = formDoc.CreateAttribute(“libraryUniqueId”);
nameAttribute.Value = libraryName;
libraryUniqueIdAttribute.Value = Guid.NewGuid().ToString(“B”);
libraryNode = formDoc.CreateElement(“Library”);
if (libraryNode.Attributes != null)
{
libraryNode.Attributes.Append(nameAttribute);
libraryNode.Attributes.Append(libraryUniqueIdAttribute);
}
if (formLibrariesNode.ChildNodes.Count > 0 && addFirst)
{
formLibrariesNode.InsertBefore(libraryNode, formLibrariesNode.FirstChild);
}
else
{
formLibrariesNode.AppendChild(libraryNode);
}
}
form[“formxml”] = formDoc.OuterXml;
Service.Update(form);
}

 

After that we’ll publish Account Entity.

public void PublishForm(Entity en)
{
var request = new PublishXmlRequest { ParameterXml = String.Format(“<importexportxml><entities><entity>{0}</entity></entities></importexportxml>”, en.GetAttributeValue<string>(“objecttypecode”)) };
Service.Execute(request);
}

 

Here is calling code

CrmConnection con = CrmConnection.Parse(“Url = https://xxxx.crm5.dynamics.com; Username=xyz@abc.onmicrosoft.com; Password=xyzxyz”);
IOrganizationService Service = new OrganizationService(con);
ScriptManage sc = new ScriptManage(Service);
var EntityName = sc.GetForm(“account”);
sc.AddLibrary(EntityName,”am_sample”, false);
sc.PublishForm(EntityName);

Now you can see JS file is added on account form!! 🙂

For more info about C# code, go through below link.

https://github.com/MscrmTools/XrmToolBox/blob/master/Plugins/MsCrmTools.FormRelated/FormLibrariesManager/AppCode/FormManager.cs

 

 

 

5

8

JS Code :

For using below code we need to add these file references.

  1. ClientGlobalContext.js.aspx
  2. jquery.min.js
  3. Sdk.Soap.min.js
function Getformxml  (EntityLogicalname) {
Sdk.jQ.setJQueryVariable($);
var SystemForm = new Sdk.Query.QueryExpression(“systemform”);
SystemForm.getDistinct();
SystemForm.addColumn(“name”);
SystemForm.addColumn(“formxml”);
SystemForm.addColumn(“objecttypecode”);
Sdk.Query.FilterExpression(Sdk.Query.LogicalOperator.And);
SystemForm.addCondition(“systemform”, “objecttypecode”, Sdk.Query.ConditionOperator.Equal, new Sdk.Query.Strings([EntityLogicalname]))
SystemForm.addCondition(“systemform”, “type”, Sdk.Query.ConditionOperator.Equal, new Sdk.Query.Ints([2]))
SystemForm.addCondition(“systemform”, “iscustomizable”, Sdk.Query.ConditionOperator.Equal, new Sdk.Query.Booleans([true]))
SystemForm.addCondition(“systemform”, “formactivationstate”, Sdk.Query.ConditionOperator.Equal, new Sdk.Query.Ints([1]))
FormxmlQuery = SystemForm;
return Sdk.jQ.retrieveMultiple(SystemForm).then(
function (ec) {
formRequestSuccesscall(ec);
})
new ErrorHandler(“An error occured “).getError(err);
}
function formRequestSuccesscall  (data) {
var $xml, $formtagxml, x = true, xml2 = ”;
if (data.getEntities().getCount() > 0) {
data.getEntities().forEach(function (n, i, arr) {
if (n.view().attributes[‘formxml’])
$xml = $($.parseXML(n.view().attributes[‘formxml’].value));
$formtagxml = $xml.find(“formLibraries”);
$($formtagxml).find(‘Library’).each(function () {
$.each(this.attributes, function (i, attrib) {
if (attrib.name == “name”) {
if (attrib.value == “Content_/scripts/wfHover.js”) {
console.log(‘already add on form!!’);
x = false;
}
}
});
});
if (x) {
if ($formtagxml.length == 0) {
xml2 += ‘<formLibraries><Library name=“am_sample” libraryUniqueId=”‘ + guid() + ‘” /></formLibraries>’;
$formtagxml = $($.parseXML(xml2)).find(“formLibraries”);
$xml.find(“form”).append($($.parseXML(xml2)).find(“formLibraries”));
} else {
$formtagxml.append(‘<Library name=“am_sample” libraryUniqueId=”‘ + guid() + ‘” />’)
}
var oSerializer = new XMLSerializer();
//clone.attributes[‘formxml’].value = oSerializer.serializeToString($xml[0]);
n.setValue(“formxml”, oSerializer.serializeToString($xml[0]));
Sdk.jQ.update(n).then(
function (id) {
// console.log(id);
publishXML(entityLogicalname);
})
}
})
}
}
function publishXML (entityName) {
var context = Xrm.Page.context;
var serverUrl = (context.getServerUrl) ? context.getServerUrl() : context.getClientUrl();
var Publishxml = “”;
Publishxml += “<s:Envelope xmlns:s=\”http:\/\/schemas.xmlsoap.org\/soap\/envelope\/\”>”;
Publishxml += ” <s:Body>”;
Publishxml += ” <Execute xmlns=\”http:\/\/schemas.microsoft.com\/xrm\/2011\/Contracts\/Services\” xmlns:i=\”http:\/\/www.w3.org\/2001\/XMLSchema-instance\”>”;
Publishxml += ” <request i:type=\”b:PublishXmlRequest\” xmlns:a=\”http:\/\/schemas.microsoft.com\/xrm\/2011\/Contracts\” xmlns:b=\”http:\/\/schemas.microsoft.com\/crm\/2011\/Contracts\”>”;
Publishxml += ” <a:Parameters xmlns:c=\”http:\/\/schemas.datacontract.org\/2004\/07\/System.Collections.Generic\”>”;
Publishxml += ” <a:KeyValuePairOfstringanyType>”;
Publishxml += ” <c:key>ParameterXml<\/c:key>”;
Publishxml += ” <c:value i:type=\”d:string\” xmlns:d=\”http:\/\/www.w3.org\/2001\/XMLSchema\”>&lt;importexportxml&gt;&lt;entities&gt;&lt;entity&gt;” + entityName + “&lt;\/entity&gt;&lt;\/entities&gt;&lt;\/importexportxml&gt;<\/c:value>”;
Publishxml += ” <\/a:KeyValuePairOfstringanyType>”;
Publishxml += ” <\/a:Parameters>”;
Publishxml += ” <a:RequestId i:nil=\”true\” \/>”;
Publishxml += ” <a:RequestName>PublishXml<\/a:RequestName>”;
Publishxml += ” <\/request>”;
Publishxml += ” <\/Execute>”;
Publishxml += ” <\/s:Body>”;
Publishxml += “<\/s:Envelope>”;
var req = new XMLHttpRequest();
req.open(“POST”, serverUrl + “/XRMServices/2011/Organization.svc/web”, true);
// 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&#8221;);
req.onreadystatechange = function () {
if (req.readyState === 4) {
if (req.status === 200) {
}
} else {
alert(“An error occurred ” + req.statusText);
}
}
req.send(Publishxml);
}

here is caling code for JS

Getformxml  (“account”);

 

Hope you will like this blog and Thank you for visiting my blog 🙂