在我们的云托管CRM 2011中,我在机会表单中有3个字段
合同条款是名为合同条款的自定义实体的查找。这些项目如下:
我想根据其他两个条目计算并填充服务关闭日期字段。我的合同条款和服务开始日期的OnChange事件的javascript代码如下:
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;
}
当用户填充计算所需的两个值时,代码将按预期运行。但是,如果其中一个字段(在本例中为Contract Term)在创建新记录时在javascript中分配了默认值,则当用户为服务开始日期赋值时,不会进行计算:
在我的函数中抛出调试器允许我调试javascript,我看到问题是什么。但是,我不明白为什么这是一个问题。
当用户手动填充这两个字段时,为什么这个确切的代码会起作用,而当其中一个字段是自动填充时却不行?该错误告诉我该对象为null,但在任何一种情况下都显然不为null。当用户手动输入值时,为什么这会起作用,而当javascript代码在表单OnLoad方法中预先填充值时,为什么不会这样?
更新
抛出上述异常的行部分是访问po_months属性 - 调试器告诉我属性为null:
ContractTermMonths = Xrm.Page.getAttribute("po_contractterm").getValue()[0].keyValues.po_months
答案 0 :(得分:3)
我认为错误很简单:Xrm.Page.getAttribute("po_contractterm").getValue()[0].keyValues
没有属性po_months
或Xrm.Page.getAttribute("po_contractterm").getValue()[0].keyValues.po_months === null
您的代码在一行中浏览了很多属性。如果你不能保证每一个属性都存在某些东西,你就会遇到麻烦。
由于我认为你仍然有点困惑,所以在错误行之前设置一个断点,并查看以下所有可能表达式中的失败。
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
我们可以删除检查表达式Xrm.Page.getAttribute("po_contractterm").getValue()
的一部分,因为该部分在if
中进行了测试。但是,检查它只是为了保持你的理智并不会有害,并且使用Visual Studio调试器,我认为你应该能够点击导航这些中的每一个,除非对象太大。知道调试器是否对你说谎也很有用,因为你的一些评论似乎表明你相信。调试器偶尔谎言,或者(更经常地)非常迟钝地呈现信息。
这是你不能懒惰的事情。好吧,也许如果你使用类似JSONPath的东西,你可能有点懒惰,但是否则,如果你不打算使用这样的工具,请确保你的路径存在需要它,或者在部分可能不存在的情况下进行适当的测试。
答案 1 :(得分:3)
我想我现在明白这个问题了。
简而言之:您假设查找字段可以访问查找记录的字段。这是不正确的。
为了扩展它,让我们从Crm实际上在查找字段中提供的内容开始。
如果您查看MSDN here。我们可以看到,当对lookup属性执行getValue()时,我们返回一个包含三个字符串属性的数组。
的EntityType 字符串:查找中显示的实体名称
ID String:查找中显示的记录的GUID值的字符串表示形式。
名 String:表示要在查找中显示的记录的文本。
注意事项:
没有keyValues
属性(我不知道你从哪里得到这个 - 请告诉我,如果我在这里遗漏了什么)。
除名称字段外,我们没有任何其他记录数据。例如:如果这是对联系人的查询,我们可以告诉其全名(来自姓名属性),但不能告诉其地址或电话号码。
因此,总结一下当Crm设置查找时它失败的原因是因为它只提供上面的信息,它不会填充keyValues
或查找记录中的任何字段,例如: po_months
。
我猜测设置查找时它的工作原理,是因为你在代码中的其他地方创建了keyValues
属性。
如果您需要通过查找来自相关记录的信息,则必须执行webservice调用以获取该信息 - 使用查找中的id。