重寫新建/更新按鈕的原因是因為項目需要用戶在新建數據時從接口對數據進行校驗,保證數據的有效性,同時獲取接口返回的部分數據完成信息填充,而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); }
填充效果如下