重写新建/更新按钮的原因是因为项目需要用户在新建数据时从接口对数据进行校验,保证数据的有效性,同时获取接口返回的部分数据完成信息填充,而Sales force的trigger仅支持@future方法异步调用接口,不能实时完成数据校验
那么重写新建/更新按钮要面临的几个核心问题:
1、lightning暂时不支持lookup字段,如果重写可能要自定义组件
2、lightning新建按钮,怎么重写在项目下新建时自动填充的父对象
点击对象管理器,新建对象项目(Test_Project),部门(Test_Department)
以下是部门(Test_Department)的字段表
标签 | API | 数据类型 | 值 |
部门名称 | Name | 文本(80) | |
项目 | Project_Dep__c | 查找(项目) | |
角色 | Role__c | 选项列表 |
项目经理 项目顾问 项目开发 项目测试 |
邮箱 | Email__c | 电子邮件 | |
报表权限 | Report_Access__c | 复选框 | |
描述 | Remarks__c | 文本区(255) |
先创建一个lightning组件Test_NewDepartment
<aura:component implements="lightning:actionOverride,
flexipage:availableForRecordHome,
force:hasRecordId,
flexipage:availableForAllPageTypes" access="global" description="Test_NewDepartment"> </aura:component>
组件继承的几个接口说明下
lightning:actionOverride:继承该接口才能覆盖标准按钮
force:hasRecordId:继承该接口才能通过“v.recordId"获取当前页面的记录ID
然后来处理第一个问题,lightning暂时不支持lookup字段的问题
经过了解,lightning提供了一个<lightning:recordEditForm>组件,通过<lightning:inputField>可以操作查找字段.
<aura:component implements="lightning:actionOverride,
flexipage:availableForRecordHome,
force:hasRecordId,
flexipage:availableForAllPageTypes" access="global" description="Test_NewDepartment">
<!-- 部门 --> <aura:attribute name="simpleDepartmentRecord" type="Test_Department__c" default="{'SobjectType':'Test_Department__c'}"/> <!-- 错误消息-->
<aura:attribute name="recordError" type="String"/>
<!-- 标记按钮能否点击--> <aura:attribute name="flag" type="Boolean" default="true"/> <div aura:id="editDialog" role="dialog" tabindex="-1" aria-labelledby="header43" class="slds-modal slds-fade-in-open"> <div class="slds-modal__container"> <div class="slds-modal__header"> <h2 class="slds-text-heading--medium">{!(v.recordId == null?'新增':'更新') + '部门'}</h2> </div> <lightning:messages /> <lightning:recordEditForm objectApiName="Test_Department__c"> <div class="slds-modal__content slds-p-around--medium slds-wrap" > <lightning:input aura:id="departmentId" label="用户名" name="userName" placeholder="请输入完整的用户名" required="true" value="{!v.simpleDepartmentRecord.Name}" /> <lightning:inputField class="customRequired" aura:id="roleId" fieldName="Role__c" value="{!v.simpleDepartmentRecord.Role__c}"/> <lightning:inputField class="customRequired" fieldName="Email__c" value="{!v.simpleDepartmentRecord.Email__c}"/> <lightning:inputField class="customRequired" aura:id="projectLookupId" fieldName="Project_Dep__c" value="{!v.simpleDepartmentRecord.Project_Dep__c}"/> <lightning:inputField class="customRequired" aura:id="reportId" fieldName="Report_Access__c" value="{!v.simpleDepartmentRecord.Report_Access__c}"/> <lightning:inputField fieldName="Remarks__c" value="{!v.simpleDepartmentRecord.Remarks__c}"/> </div> <div class="slds-modal__footer"> <lightning:button variant="neutral" label="Cancel" onclick="{!c.cancelDialog}" /> <lightning:button variant="brand" label="Submit" onclick="{!c.saveRecord}" disabled="{!v.flag}"/> </div> </lightning:recordEditForm> </div> </div>
<!-- 弹窗打开的时候,用一个遮罩层将页面变暗-->
<div aura:id="overlay" class="slds-backdrop slds-backdrop--open"></div> </aura:component>
此时预览下页面查看效果
通过<lightning:recordEditForm>组件,就能比较方便的重写新建/更新按钮,但此时会出现一个问题
当点击更新按钮的时候,会发现使用<lightning:input>的用户名没有办法进行更新,此时查阅相关文档
<Lightning:recordEditForm> 发现这样一句话:
The lightning:inputField component is used inside the lightning:recordEditForm to create editable fields.
The lightning:outputField component and other display components such as lightning:formattedName can be used to
display read-only information in your form.
简单说,除了使用<lightning:inputField>的字段是可编辑的,lightning:input,lightning:formattedName等其他标签都是只读的
于是这里就遇到一个很严重的问题,查阅文档知道lightning:inputField字段不支持onblur属性,它支持onchange属性,而需求是在输入用户名后通过接口实时对输入的数据进行校验并获取返回的用户ID.
直接操作看起来不太可行,于是想到了迂回解决的办法,把更新也当作新建处理.
在点击更新的时候,将页面记录ID传到后台进行初始化,把查询出来的部门信息反向填充到表单中,这样就能绕开<lightning:recordEditForm>更新时lightning:input无法编辑,而lightning:inputField又不支持onblur属性的问题.
PS:
此处补充一个<lightning:recordEditForm>组件的小问题,<lightning:recordEditForm>在提交按钮 <lightning:button variant="brand" label="Submit" onclick="{!c.saveRecord}" type="submit"/> 会有一个默认的提交行为,所以不小心就会出现提交两次的问题,此时在JSController提交方法中设置
// 取消默认的提交行为
event.preventDefault();
就能取消组件的默认提交行为,以下是文档的描述
To customize the behavior of your form when it loads or when data is submitted, use theonload
andonsubmit
attributes
to specify event handlers. If you capture the submit event and submit the form programmatically,
useevent.preventDefault()
to cancel the default behavior of the event. This prevents a duplicate form submission.
接下来处理第二个问题:在父对象项目的相关列表中创建部门对象时,如何自动填充父对象的问题.
很遗憾, Salesforce没有提供类似v.recordId这样的属性可以直接获取父级id,甚至在查阅解决方案的时候发现有人提了Idea
后来有个想法就是说不管怎么设计,相关列表创建子对象记录一定绕不开的就是通过url传递父对象的ID
所以在组件的Helper.js中写一个解析URL的方法
// 获取URL参数
getUrlParameter : function(component,event,name) {
name = name.replace(/[[]]/g, "\$&");
var url = window.location.href;
var regex = new RegExp("[?&]" + name + "(=1.([^&#]*)|&|#|$)");
var results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/+/g, " "));
}
在组件的Controller.js中打印父级ID
doInit : function(component, event, helper){
// 获取可能的父级id
var value = helper.getUrlParameter(component,event,'inContextOfRef');
var context = JSON.parse(window.atob(value));
var parentId = context.attributes.recordId;
console.log('*** parentId:' + parentId);
},
判断如果parentId存在,则将Id传递到后台,查询父对象的信息并返回数据进行填充
// 从父级对象创建部门的时候给对应的字段预填充 @AuraEnabled public static String initFunction(String parentId){ System.debug('*** parentId:' + parentId); Test_Department__c permiss = new Test_Department__c(); // 考虑权部门以后除了项目还有其他的主表,这里要检验parentId属于那个对象 String prefix = Test_Project__c.sobjecttype.getDescribe().getKeyPrefix(); if (parentId.substring(0, 3) == prefix) { permiss.Project_Dep__c = parentId; } System.debug('*** 部门:' + permiss); return JSON.serialize(permiss); }
填充效果如下