Lightning-覆盖标准按钮(5)

现在我们已经成功地重写了New按钮,只需要一点点工作,我们也可以重用组件来覆盖Edit按钮。这实际上有点愚蠢,因为当我们覆盖Edit按钮时,它也禁用标准记录页面的内联编辑能力。这意味着我们永远无法编辑对话框中的五个字段。但是,让我们这样做,因为它可能在另一个环境中有用。

创建代码来处理上下文

  1. 在Developer Console中,切换到PropertyDialog组件。
  2. 在force之前的新行上添加新的aura:属性:recordData:
    <aura:attribute name="modalContext" type="String" default="New" />
    
  3. 将作为模式标题的<h2>标签更改为:
    <h2 class="slds-text-heading--medium">{!v.modalContext} Record</h2>
    

    通过将标题的上下文定义为aura:属性,当模式用于编辑记录时,我们可以轻松地将其从“新建”更改为“编辑”。

  4. 切换到PropertyDialogController。
  5. 在doInit:function(component,event,helper){下面添加一个新行{并添加下面的代码:
    var recId = component.get("v.recordId");
    if (recId) {
        component.set("v.modalContext", "Edit");
    }
    
  6. 在if语句中包装函数的其余部分:
    if (!recId) {
        component.find("forceRecord").getNewRecord(
            "Property__c",
            null,
            false,
            $A.getCallback(function() {
                var rec = component.get("v.propertyRecord");
                var error = component.get("v.recordError");
                if (error || (rec === null)) {
                    console.log("Error initializing record template: " + error);
                    return;
                }
            })
        ); 
    }
    
    现在,当组件加载时,它检查recordId的存在。当然,当它与New按钮一起使用时,没有recordId;因此,该功能创建新的记录。但是,如果recordId存在,modalContext属性设置为Edit。
  7. 保存这两个文件。

预填充字段

当我们使用对话框编辑记录时,我们显然需要当前的字段值已经在对话框中(你不能编辑你看不到的东西)。

  1. 切换回PropertyDialog组件。
  2. 添加 value="{!v.propertyRecord.Name}"value="{!v.propertyRecord.Beds__c}"value="{!v.propertyRecord.Baths__c}", 和 value="{!v.propertyRecord.Price__c}" 到相应的lightning:input 标签.
  3. 添加 value="{!v.propertyRecord.Status__c}" 到 lightning:select.

    你的代码应该是这样的:

    <lightning:input aura:id="propName" name="propName" label="Property Name" value="{!v.propertyRecord.Name}" required="true" class="slds-size--1-of-1 slds-p-horizontal_x-small" />
    <lightning:input aura:id="propBeds" name="propBeds" label="Beds" value="{!v.propertyRecord.Beds__c}" class="slds-size--1-of-2 slds-p-horizontal_x-small" />
    <lightning:input aura:id="propBaths" name="propBaths" label="Baths" value="{!v.propertyRecord.Baths__c}" class="slds-size--1-of-2 slds-p-horizontal_x-small" />
    <lightning:input aura:id="propPrice" name="propPrice" label="Price" value="{!v.propertyRecord.Price__c}" class="slds-size--1-of-2 slds-p-horizontal_x-small" />    
    <lightning:select aura:id="propStatus" name="propStatus" label="Status" value="{!v.propertyRecord.Status__c}" class="slds-size--1-of-2 slds-p-horizontal_x-small">
        <aura:iteration items="{!v.picklistValues}" var="item">
            <option value="{!item}">{!item}</option>
        </aura:iteration>
    </lightning:select>
    
  4. 保存文件。

更新取消按钮

在财产记录页面上,当用户点击取消按钮,现在他们重新回到属性列表页面。让我们改变这一点,以便用户最终在财产记录页上。

  1. 切换回PropertyDialogController。
  2. 用以下代码替换cancelDialog函数:
    cancelDialog: function(component, event, helper) {
        var recId = component.get("v.recordId");
        if (!recId) {
            var homeEvt = $A.get("e.force:navigateToObjectHome");
            homeEvt.setParams({
                "scope": "Property__c"
            });
            homeEvt.fire();
        } else {
            helper.navigateTo(component, recId);
        }
    }
    
    再一次,我们检查一下recordId是否存在。如果是这样,我们知道我们正在一个记录页面,并将返回到该页面。
  3. 保存文件。
  4. 切换回您的组织并单击替代文本:设置图标alt text: Setup Icon并选择 Setup
  5. 点击 Object Manager.
  6. 点击 Property.
  7. 点击 Buttons, Links, and Actions.
  8. 点击 alt text: Dropdown menu icon 然后选择编辑。
  9. 选择覆盖 Lightning Component Bundle.
  10. 选择 c:PropertyDialog 作为要覆盖的包,然后单击保存。
  11. 点击应用启动器图标alt text: App Launcher icon,然后选择Dreamhouse Lightning。
  12. 单击“属性”,然后单击任何属性名称以导航到其属性记录页面,然后刷新此页面。
  13. 单击编辑按钮以在记录页面的上下文中测试对话框。

高五分! 正如你刚刚学到的,使用Lightning组件覆盖标准动作和按钮是非常容易的。 当然,这样做有一些考虑,但这个过程本身是非常简单的。 现在,去超越!

Lightning-覆盖标准按钮(4)

我们终于到了!现在是时候将我们新的Lightning组件用作标准按钮覆盖。这实际上很简单,几乎可以用你创建的任何Lightning组件完成。有几个考虑因素,但我们很快就会解决。

添加覆盖界面

  1. 在您的组织的财产记录页面上,单击替代文本:设置图标alt text: Setup Icon,然后选择 Edit Page.
  2. 点击我们新的Lightning组件选择它,然后点击alt text: Delete component:删除组件将其从页面中删除。
  3. 单击保存,然后单击返回返回到您的属性详细信息页面。

    现在,我们准备将该组件用作按钮覆盖,因此不必再将其放在页面上。

  4. 在Developer Console中,切换回PropertyDialog组件。
  5. 将lightning:actionOverride添加到aura:component标签中的接口列表中。它现在应该是这样的:
    <aura:component implements="flexipage:availableForRecordHome,force:hasRecordId,lightning:actionOverride" access="global" >
    
  6. 保存文件。

    lightning:actionOverride 是神奇的界面,指示Lightning Experience让我们使用这个组件来覆盖标准的按钮或动作。

设置覆盖

  1. 回到您的组织中,单击alt text: Setup Icon:设置图标并选择设置。
  2. 点击 Object Manager.
  3. 点击 Property.
  4. 点击 Buttons, Links, and Actions.
  5. 点击 alt text: Dropdown menu icon 旁边的新建,然后选择 Edit.
  6. 选择覆盖 Lightning Component Bundle.
  7. 选择c:PropertyDialog作为要用其覆盖的包。

    alt text: Override with Lightning Component

    选择列表将列出组织中具有闪电:actionOverride接口声明的所有组件。

  8. 点击 Save.
  9. 点击 alt text: App Launcher icon 然后选择Dreamhouse闪电,然后点击属性。
  10. 刷新此页面,然后单击新建以创建新的属性。

    就在那里!您已使用Lightning组件覆盖了Property对象上的标准New按钮。

    注意:如果您没有看到新的表单,则可能需要重新刷新页面。单击属性,刷新页面,然后单击新建。

将SLDS样式添加到我们的闪电组件

朋友之间,你不得不承认,组件不是很漂亮。当您使用Lightning组件作为覆盖时,它会填充整个页面。所以让我们来添加一点SLDS魔术,让它看起来更好。

  1. 在Developer Console中,将PropertyDialog组件的整个代码替换为:
    <aura:component implements="lightning:actionOverride,flexipage:availableForRecordHome,force:hasRecordId" access="global">
        <aura:attribute name="picklistValues" type="Object" />
        <aura:attribute name="propertyRecord" type="Property__c" />
        <force:recordData aura:id="forceRecord"
                          recordId="{!v.recordId}"
                          targetFields="{!v.propertyRecord}"
                          fields="Id,Name,Beds__c,Baths__c,Price__c,Status__c"
                          mode="EDIT" />
        <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
    
        <c:PickListValues sObjectName="Property__c" fieldName="Status__c" picklistValues="{!v.picklistValues}" />
    
        <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">New Record</h2>
                </div>
                <div class="slds-modal__content slds-p-around--medium slds-grid slds-wrap ">
                    <lightning:input aura:id="propName" name="propName" label="Property Name" required="true" class="slds-size--1-of-1 slds-p-horizontal_x-small" />
                    <lightning:input aura:id="propBeds" name="propBeds" label="Beds" class="slds-size--1-of-2 slds-p-horizontal_x-small" />
                    <lightning:input aura:id="propBaths" name="propBaths" label="Baths" class="slds-size--1-of-2 slds-p-horizontal_x-small" />
                    <lightning:input aura:id="propPrice" name="propPrice" label="Price" class="slds-size--1-of-2 slds-p-horizontal_x-small" />    
                    <lightning:select aura:id="propStatus" name="propStatus" label="Status" class="slds-size--1-of-2 slds-p-horizontal_x-small">
                        <aura:iteration items="{!v.picklistValues}" var="item">
                            <option value="{!item}">{!item}</option>
                        </aura:iteration>
                    </lightning:select>
                </div>
                <div class="slds-modal__footer">                
                    <lightning:button variant="neutral" label="Cancel" />
                    <lightning:button variant="brand" label="Submit" onclick="{!c.saveRecord}" />
                </div>
            </div>
        </div>
        <div aura:id="overlay" class="slds-backdrop slds-backdrop--open"></div>
    </aura:component>
    
    使用Salesforce Lightning Design System中模式的标记使页面看起来更好。
  2. 保存文件。
  3. 在您的组织中,刷新属性页面以查看新模型。如果您不在表单上,​​然后单击新建以查看它。

alt text: New record dialog

现在看起来不太好?

启用取消按钮

  1. 在开发人员控制台的PropertyDialog组件中,将onclick处理程序onclick =“{!c.cancelDialog}”添加到“取消”按钮。
  2. 保存文件。
  3. 切换到PropertyDialogController并添加以下代码以创建一个新的cancelDialog函数,该函数将组件和帮助器作为参数(不要忘记逗号):
    cancelDialog : function(component, helper) {
    }
    
  4. 添加以下功能:
    var homeEvt = $A.get("e.force:navigateToObjectHome");
    homeEvt.setParams({
        "scope": "Property__c"
    });
    homeEvt.fire();
    
    与我们创建的navigateTo函数类似,此函数只是调用navigateToObjectHome事件,将用户发送回主“属性”页面。
  5. 保存文件。
  6. 在您的组织中,刷新属性页面,然后单击取消。

    你回到属性首页。

Lightning-覆盖标准按钮(3)

当从Visualforce世界转移到Lightning组件时,开发人员面临的一个重大变化是如何与服务器通信。直到Summer ’17发布,这意味着创建一个Apex类来做任何事情,甚至是在Visualforce中“自动”处理的简单的CRUD交互。随着夏季’17发布和闪电数据服务的引入,这一切都改变了。因此,对于我们的组件,我们使用Lightning Data Service创建新的属性记录 – 无需编写Apex!

添加force:recordData

  1. 在开发人员控制台的PropertyDialog组件中,在刚添加的aura:attribute和c:PickListValues之间添加以下内容:
    <aura:attribute name="propertyRecord" type="Property__c" />
    <force:recordData aura:id="forceRecord"
                    recordId="{!v.recordId}"
                    targetFields="{!v.propertyRecord}"
                    fields="Id,Name,Beds__c,Baths__c,Price__c,Status__c"
                    mode="EDIT" />
    

    Lightning Data Service使用名为force:recordData的对象在记录上执行CRUD交互。 force有几个其他的属性:recordData,但是为了我们的目的,我们只需要recordId,targetRecord,fields和mode。

    当值被分配给recordId属性时,在场景后面,Lightning Data Service将检索整个记录或请求的字段。结果字段存储在由targetFields属性定义的属性中;在这种情况下,propertyRecord。最后,mode属性定义了force:recordData的这个实例是处于VIEW模式还是EDIT模式。显然,由于我们正在创建一个记录,它需要处于编辑模式。

初始化新记录

  1. 在force之后的新行添加以下内容:recordData标记:
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
    
  2. 单击侧面导航中的“控制器”以将控制器添加到组件。
  3. 将默认函数myAction重命名为doInit,并将以下内容添加到函数中:
    component.find("forceRecord").getNewRecord(
            "Property__c",
            null,
            false,
            $A.getCallback(function() {
                var rec = component.get("v.propertyRecord");
                var error = component.get("v.recordError");
                if (error || (rec === null)) {
                    console.log("Error initializing record template: " + error);
                    return;
                }
            })
        );
    
    强制的getNewRecord:recordData有四个参数。第一个参数Property__c定义要创建记录的sObject的实体API名称。下一个参数是recordTypeId。我们将其设置为空,它只是说根据用户的配置文件使用默认的记录类型。第三个参数决定是否从客户端缓存加载记录模板。最后,回调检查是否有错误或者propertyRecord属性是否未被填充。

保存新记录

  1. 在PropertyDialogController中添加一个名为saveRecord的新函数,并传递组件,事件,帮助器作为参数:
    saveRecord : function(component, event, helper) {
    }
    
    不要忘记逗号分隔功能!
  2. 将以下内容添加到新功能中:
    var propBeds = parseInt(component.find('propBeds').get("v.value"), 10);
    var propBaths = parseInt(component.find('propBaths').get("v.value"), 10);
    var propPrice = parseInt(component.find('propPrice').get("v.value"), 10);
    
    component.set("v.propertyRecord.Name", component.find('propName').get("v.value"));    
    component.set("v.propertyRecord.Beds__c", propBeds);
    component.set("v.propertyRecord.Baths__c", propBaths);
    component.set("v.propertyRecord.Price__c", propPrice);
    component.set("v.propertyRecord.Status__c", component.find('propStatus').get("v.value"));
    
    var tempRec = component.find("forceRecord");
    tempRec.saveRecord($A.getCallback(function(result) {
        console.log(result.state);
        var resultsToast = $A.get("e.force:showToast");
        if (result.state === "SUCCESS") {
            resultsToast.setParams({
                "title": "Saved",
                "message": "The record was saved."
            });
            resultsToast.fire();                
        } else if (result.state === "ERROR") {
            console.log('Error: ' + JSON.stringify(result.error));
            resultsToast.setParams({
                "title": "Error",
                "message": "There was an error saving the record: " + JSON.stringify(result.error)
            });
            resultsToast.fire();
        } else {
            console.log('Unknown problem, state: ' + result.state + ', error: ' + JSON.stringify(result.error));
        }
    }));
    

    当我们保存记录时,我们确保字段类型的值是正确的。 Beds__c,Baths__c和Price__c都被设置为Property_c对象中的整数。因此,当我们从输入中获取值时,我们使用parseInt JavaScript方法将其从一个字符串转换为一个整数。一旦转换,我们更新propertyRecord属性中的值以及来自其他表单字段的值。

    接下来,我们使用tempRec的变量赋值来调用saveRecord的force:recordData方法,以将记录的新值保存回Salesforce。哦,我们是否提到过那是?真的,tempRec.saveRecord(),我们完成了!

    当然,在saveRecord方法的回调中还有更多。确保记录成功保存后,我们吐出一杯祝酒词,让用户知道保存是否奏效。

  3. 保存PropertyDialogController.js并切换回PropertyDialog组件。
  4. onclick="{!c.saveRecord}" 添加到提交对话框的lightning:button   (标签为“submit”的按钮).
  5. 保存文件。

导航到保存后的新记录

记录保存后,我们不希望对话框坐在那里。因此,我们可以选择:导航到“属性”列表或新创建的记录。让我们做一个行政决定,并导航到新创建的记录。

  1. 在开发人员控制台中,单击侧面导航栏中的“助手”以将助手文件添加到组件。

    当您最初开始构建Lightning组件时,将所有JavaScript函数放在控制器文件中感觉很自然。但是,在控制器文件中,不能从另一个函数调用一个函数。所以,在我们的例子中,如果我们构建了一个导航到记录的函数,我们不能从saveRecord函数中调用它。这意味着我们必须将整个功能写入saveRecord函数。这很糟糕 – 这可能会导致我们在稍后的函数中重复我们的代码。因此,将任何可能需要调用多次或从另一个函数中调用的任何东西放到帮助程序文件中是一种更好的做法。

  2. 将帮助程序文件的默认内容替换为:
    ({
        navigateTo: function(component, recId) {
            var navEvt = $A.get("e.force:navigateToSObject");
            navEvt.setParams({
                "recordId": recId
            });
            navEvt.fire();
        }
    })
    
    这个函数只是调用内置的平台事件force:navigateToSObject,传递我们从recordSave的回调中得到的recordId。
  3. 保存文件。
  4. 切换回PropertyDialogController.js。
  5. 在resultsToast.fire()之后的新行中添加以下内容:在回调的成功状态(在第40行附近):
    var recId = result.recordId;
    helper.navigateTo(component, recId);
    
  6. 保存文件,然后返回到您的组织并刷新属性详细信息页面。
  7. 用这些值填写表单:
    • Name: 123 Main St.
    • Beds: 4
    • Baths: 3
    • Price: 500000
    • Status: Pre-Market
  8. 点击提交。

alt text: The record was successfully saved.

你印象深刻吗?你只是保存了一个新的记录而不用写任何Apex代码去做!即使你是一个性格开朗的开发者,也会觉得非常神奇。接下来,让我们完成我们设定的操作并覆盖“新建”按钮。