In our cloud-hosted CRM 2011 I have 3 fields on an opportunity form
- Contract Term (Lookup)
- Service Start Date (Date And Time)
- Service Close Date (Date And Time)

Contract Term is a Lookup on a custom entity called Contract Terms. The items are listed below:

I want to calculate and populate the Service Close Date field based on entries in the other two. My javascript code for the OnChange event of Contract Term and Service Start Date is as follows:
function UpdateAgreementCloseDate() {
//debugger;
if (Xrm.Page.getAttribute("po_contractterm").getValue() != null && Xrm.Page.getAttribute("po_agreementstartdate").getValue() != null)
{
//Get Months from agreement term
var ContractTermMonths = 0;
ContractTermMonths = Xrm.Page.getAttribute("po_contractterm").getValue()[0].keyValues.po_months.value;
//Get Start Date
var currentAgreementStartDate;
currentAgreementStartDate = Xrm.Page.getAttribute("po_agreementstartdate").getValue();
//Add contract term monthsto start date
var AgreementCloseDate = getExpirationDate(currentAgreementStartDate, parseFloat(ContractTermMonths));
Xrm.Page.data.entity.attributes.get("po_agreementclosedate").setValue(AgreementCloseDate);
Xrm.Page.data.entity.attributes.get("po_agreementclosedate").setSubmitMode("always"); // Save the Disabled Field
}
}
function getExpirationDate(tempdate, numberofmonths) {
var next_month = tempdate.getMonth() + numberofmonths;
var next_year = tempdate.getFullYear();
if (next_month > 11) {
if (numberofmonths > 11) {
var extrayears = parseInt(next_month / 12);
var remainingmonths = next_month % 12;
next_month = remainingmonths;
next_year = next_year + extrayears;
}
else {
next_month = 0;
next_year++;
}
}
tempdate.setMonth(next_month);
tempdate.setYear(next_year);
return tempdate;
}
When the user populates the two values that are required for the calculation, the code runs as expected. But if one of the fields (in this case Contract Term) has a default value assigned in javascript on the creation of a new record, the calculation doesn’t occur when the user gives a value to Service Start Date:

Throwing debugger in my function allows me to debug the javascript and I see what the problem is. But, I don’t understand why it’s a problem.

Why would this exact code work when the user manually populates both fields, but not when one of them is auto populated? The error is telling me that the object is null, but clearly it is not null in either case. Why would this work when the user manually enters a value, but not when the value is prepopulated in the forms OnLoad method by javascript code?
UPDATE
The part of the line that throws the exception above is accessing the po_months property – debugger tells me the property is null:
ContractTermMonths = Xrm.Page.getAttribute("po_contractterm").getValue()[0].keyValues.po_months
I think I understand this problem now.
In short: You are assuming that a lookup field will give you access to the fields of the lookup’ed record. This is incorrect.
To expand on that, lets start with what Crm actually gives you in a lookup field.
If you have a look at the MSDN here. We can see that when getValue() is performed on a lookup attribute we are returned an array with three string properties.
Things to note:
There is no
keyValuesproperty (I’m not sure where you have got this from – please let me know if I’m missing something here).Apart from the name field the we don’t have any other record data. E.g: If this was a lookup to a contact we could tell its fullname (from the name property) but not its address or phone number.
So, to summarise the reason it fails when Crm sets the lookup is because it only provides the information from above, it will not populate
keyValuesor any of the fields from the lookup’ed record, e.g.po_months.I’m guessing the reason it works when you set the lookup, is because you are creating the
keyValuesproperty somewhere else in code.If you want information from a record related via a lookup, you have to perform a webservice call to get that information – using the id from the lookup.