locked
CRM 2011 - Update old and new lookup record using oData RRS feed

  • Question

  • Hi Guys,

    On my entity A form, I have a lookup filed which is Entity B (one to many relationship)

    Now I want to update attribute on entity B when user will change the lookup value on Entity A form.

    I want to change attribute on both outgoing and incoming lookup value record. How can I accomplish this using oData?

    I have gone thru SDK example of updating record using oData but I don't know how to read Lookup old and new both the value using 'Onchange' or 'Onsave' event so that I can update those 2 records.

    For Example,

    On opportunity form, I have a lookup control of Account entity.

    Whenever user change the account lookup value on opportunity form, old and new account record should get updated with todays date. How to do this using oData.

    Thanks for your time

    Wednesday, February 1, 2012 11:23 PM

Answers

  • Hi,

    When a field is changed, there isn't a direct way to get what the field value was before being changed.

    One way to get around this would be to get the value of the field when the form loads and use that when the field is changed.

    Something like this:

     

    // Variable to store the original field value
    var _originalFieldValue = null;
    
    // Form load event
    function OnFormLoad()
    {
    	// If this isn't a new record, get the original field value
    	if (Xrm.Page.ui.getFormType() != 1)
    	{
    		_originalFieldValue = Xrm.Page.getAttribute('fieldname').getValue();
    	}
    }
    
    // Form field changed event
    function OnFieldChanged()
    {
    	var currentFieldValue = Xrm.Page.getAttribute('fieldname').getValue();
    	
    	// Update the previous record
    	UpdateRelatedRecord(_originalFieldValue);
    	
    	// Update the new record
    	UpdateRelatedRecord(currentFieldValue);
    	
    	// Store the current value as the previous value
    	_originalFieldValue = currentFieldValue;
    }
    
    // Returns the URL to the REST endpoint URL
    function GetRestEndpointUrl()
    {
    	var serverUrl = Xrm.Page.context.getServerUrl();
    
    	if (serverUrl.substr(serverUrl.length - 1) != '/')
    	{
    		serverUrl += '/';
    	}
    
    	return serverUrl + '/XRMServices/2011/OrganizationData.svc/';
    }
    
    function UpdateRelatedRecord(value)
    {
    	if (value == null || value[0] == null)
    	{
    		// Ignore empty values
    		return;
    	}
    	
    	// Add oData code to update the field on the related record
    	var relatedRecord = new Object();
    	
    	// Store the current date/time in your custom field
    	relatedRecord.new_lastmodified = new Date();
    	
    	// oData update request
    	var request = new XMLHttpRequest();
    	request.open('POST', GetRestEndpointUrl() + "AccountSet(guid'" + value[0].id + "')", true);
    	request.setRequestHeader('Accept', 'application/json');
    	request.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
    	request.setRequestHeader('X-HTTP-Method', 'MERGE');
    	request.onreadystatechange = function ()
    	{
    		if (this.readyState == 4)
    		{
    			if (this.status == 204 || this.status == 1223)
    			{
    				alert('Updated record');
    			}	
    			else
    			{
    				alert('Update failed');
    			}
    	    }
    	};
    	request.send(JSON.stringify(relatedRecord));
    }
    

     


    This will update the new_lastupdated field on the account entity when an account lookup is changed for the previous and current lookup values if specified. Is this the kind of thing you are looking for?

     

    Cheers,
    Tully

    • Marked as answer by H.Desai Thursday, February 2, 2012 9:13 PM
    Thursday, February 2, 2012 2:24 AM
  • Hi H.Desai,

    The _originalFieldValue is global variable because it is not defined in the scope of a function. In the form load event it is setting the value, but the variable has already been defined.

    var _globalVariable = null;
    
    function OnLoadEvent()
    {
    	// Declare a local variable, only accessible in the scope of the OnLoad function
    	var localVariable = 'this is local';
    	
    	// Alert the local variable - "this is local"
    	alert(localVariable);
    	
    	// Assign a value for the global variable
    	_globalVariable = 'this is global';
    	
    	// Alert the global variable - "this is global"
    	alert(_globalVariable);
    }
    
    function OnChangeEvent()
    {
    	// Alert the global variable - "this is global"
    	alert(_globalVariable);
    	
    	// Alert the local variable - this will not show a value because localVariable is not global and was defined in the scope of another function
    	alert(localVariable);
    }
    

    Have a look here for more information on JavaScript variables and local / global scopes: http://www.w3schools.com/js/js_variables.asp

     

    Cheers,
    Tully 

    • Marked as answer by H.Desai Friday, February 3, 2012 1:09 AM
    Thursday, February 2, 2012 10:34 PM

All replies

  • Hi,

    When a field is changed, there isn't a direct way to get what the field value was before being changed.

    One way to get around this would be to get the value of the field when the form loads and use that when the field is changed.

    Something like this:

     

    // Variable to store the original field value
    var _originalFieldValue = null;
    
    // Form load event
    function OnFormLoad()
    {
    	// If this isn't a new record, get the original field value
    	if (Xrm.Page.ui.getFormType() != 1)
    	{
    		_originalFieldValue = Xrm.Page.getAttribute('fieldname').getValue();
    	}
    }
    
    // Form field changed event
    function OnFieldChanged()
    {
    	var currentFieldValue = Xrm.Page.getAttribute('fieldname').getValue();
    	
    	// Update the previous record
    	UpdateRelatedRecord(_originalFieldValue);
    	
    	// Update the new record
    	UpdateRelatedRecord(currentFieldValue);
    	
    	// Store the current value as the previous value
    	_originalFieldValue = currentFieldValue;
    }
    
    // Returns the URL to the REST endpoint URL
    function GetRestEndpointUrl()
    {
    	var serverUrl = Xrm.Page.context.getServerUrl();
    
    	if (serverUrl.substr(serverUrl.length - 1) != '/')
    	{
    		serverUrl += '/';
    	}
    
    	return serverUrl + '/XRMServices/2011/OrganizationData.svc/';
    }
    
    function UpdateRelatedRecord(value)
    {
    	if (value == null || value[0] == null)
    	{
    		// Ignore empty values
    		return;
    	}
    	
    	// Add oData code to update the field on the related record
    	var relatedRecord = new Object();
    	
    	// Store the current date/time in your custom field
    	relatedRecord.new_lastmodified = new Date();
    	
    	// oData update request
    	var request = new XMLHttpRequest();
    	request.open('POST', GetRestEndpointUrl() + "AccountSet(guid'" + value[0].id + "')", true);
    	request.setRequestHeader('Accept', 'application/json');
    	request.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
    	request.setRequestHeader('X-HTTP-Method', 'MERGE');
    	request.onreadystatechange = function ()
    	{
    		if (this.readyState == 4)
    		{
    			if (this.status == 204 || this.status == 1223)
    			{
    				alert('Updated record');
    			}	
    			else
    			{
    				alert('Update failed');
    			}
    	    }
    	};
    	request.send(JSON.stringify(relatedRecord));
    }
    

     


    This will update the new_lastupdated field on the account entity when an account lookup is changed for the previous and current lookup values if specified. Is this the kind of thing you are looking for?

     

    Cheers,
    Tully

    • Marked as answer by H.Desai Thursday, February 2, 2012 9:13 PM
    Thursday, February 2, 2012 2:24 AM
  • Hi Tully,

    Many thanks for this solution. I will give it a go.

    My only concern is, how I am going read the vaue of the _originalFieldValue varibale in form's onchange event as this value is stored in onload event function.

    Can we pass the variable value from onload event to onchange event function?

    Appreciate your time.

    Cheers,

    H.Desai


    • Edited by H.Desai Thursday, February 2, 2012 9:29 PM
    Thursday, February 2, 2012 9:13 PM
  • Hi H.Desai,

    The _originalFieldValue is global variable because it is not defined in the scope of a function. In the form load event it is setting the value, but the variable has already been defined.

    var _globalVariable = null;
    
    function OnLoadEvent()
    {
    	// Declare a local variable, only accessible in the scope of the OnLoad function
    	var localVariable = 'this is local';
    	
    	// Alert the local variable - "this is local"
    	alert(localVariable);
    	
    	// Assign a value for the global variable
    	_globalVariable = 'this is global';
    	
    	// Alert the global variable - "this is global"
    	alert(_globalVariable);
    }
    
    function OnChangeEvent()
    {
    	// Alert the global variable - "this is global"
    	alert(_globalVariable);
    	
    	// Alert the local variable - this will not show a value because localVariable is not global and was defined in the scope of another function
    	alert(localVariable);
    }
    

    Have a look here for more information on JavaScript variables and local / global scopes: http://www.w3schools.com/js/js_variables.asp

     

    Cheers,
    Tully 

    • Marked as answer by H.Desai Friday, February 3, 2012 1:09 AM
    Thursday, February 2, 2012 10:34 PM
  • Hi Tully,

    Yes, of course. It was a stupid question from me as in CRM 2011 Javascript is a part of the webresource. I simply confused my self.

    Thanks for your clarification.

    Cheers,

    H.Desai

    Friday, February 3, 2012 1:09 AM