简体   繁体   中英

CRM 2011 javascript error - object is undefined, when clearly it is defined

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 the error is pretty straightforward: either Xrm.Page.getAttribute("po_contractterm").getValue()[0].keyValues has no property po_months or Xrm.Page.getAttribute("po_contractterm").getValue()[0].keyValues.po_months === null

Your code is navigating through a lot of properties on one line. If you cannot guarantee the existence of something at every one of those properties, you're asking for trouble.

Since I think you're still a bit confused, set a breakpoint just before the error line and see , of all the following possible expressions, what fails.

Xrm.Page.getAttribute("po_contractterm").getValue()  //this shouldn't be null
Xrm.Page.getAttribute("po_contractterm").getValue()[0]
Xrm.Page.getAttribute("po_contractterm").getValue()[0].keyValues
Xrm.Page.getAttribute("po_contractterm").getValue()[0].keyValues.po_months  //this probably doesn't exist or is null.
Xrm.Page.getAttribute("po_contractterm").getValue()[0].keyValues.po_months.value

We can eliminate checking part of the expression Xrm.Page.getAttribute("po_contractterm").getValue() because that part is tested in the if . It wouldn't hurt to check it just to keep your sanity, though, and with the Visual Studio debugger, I would think you should be able to click navigate through each of these anyway, unless the object is too large. It'd also be useful to know if the debugger is lying to you, as some of your comments seem to suggest you believe. Debuggers do occasionally lie, or (much more often) present information quite obtusely.

This is something you can't be lazy with. Well, maybe if you use something like JSONPath , you can be a bit lazy, but otherwise, if you are not going to use a tool like that, make sure the path exists when you need it, or do proper testing in case parts of it might not exist.

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.

entityType String: the name of the entity displayed in the lookup

id String: The string representation of the GUID value for the record displayed in the lookup.

name String: The text representing the record to be displayed in in the lookup.

Things to note:

There is no keyValues property (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. Eg: 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 keyValues or any of the fields from the lookup'ed record, eg po_months .

I'm guessing the reason it works when you set the lookup, is because you are creating the keyValues property 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM