Lightning-设计(3)网格系统

学习目标

完成本单元后,您将能够:

  • 描述网格系统组件如何工作。
  • 使用网格系统布局对象主页/列表视图页面。

什么是网格系统?

除了最简单的页面和组件外,其他所有的基础都是某种布局网格。设计系统为此目的提供了一个专门的组件,这个目的被称为网格系统。如果您使用了其他CSS框架(如Bootstrap),则您将熟悉网格的概念。如果没有,非常简短地说,一个网格允许你把你的页面分成行和列。然后,您可以安排您的标记,使其呈现在特定的行/列中。网格可以嵌套,以实现复杂的布局。

设计系统网格基于CSS Flexbox,并提供灵活的,移动优先的,设备无关的脚手架系统。设计系统还包含助手类,可以用来改变网格的外观和行为,例如对齐,顺序,流动和填充。

网格系统允许您通过为小型,中型和大型屏幕定义特定布局变体来创建响应式页面。这些分别定义为480px,768px和1024px的断点。裁剪响应式页面的细节超出了本教程的范围,但如果您想了解更多信息,请参阅尺寸实用工具页面文档。

如何使用网格系统

网格系统基于两个关键构建块:网格包装(用slds-grid类指定)和其中的列(用slds-col类指定)。这是一个例子:

要开始,将slds-grid类添加到外部包装器元素。然后在里面添加所需数量的列,通过添加slds-col类到子元素。在这种情况下,我们将使用<div>元素。例如,这是一个简单的三列网格:

<div class="slds-grid">
  <div class="slds-col">Column 1</div>
  <div class="slds-col">Column 2</div>
  <div class="slds-col">Column 3</div>
</div>
这个标记导致以下布局:

Sample easy grid

默认情况下,列的大小与其内容相关。在这个简单的例子中,我们应该看到三个相同间距的列,因为它们拥有相同数量的内容。如果更多的内容被添加到其中一列,它会相对于其他内容增长。

您还可以使用大小助手类来手动指定列的大小。这些使用slds-size-X-Y格式,其中X表示总空间Y的一部分。例如,slds-size-1-2表示宽度为可用空间的50%。使用手动调整大小等级帮助程序,您可以在以下网格中指定列比率 – 2,3,4,5,6和12。

这是修改上面的例子,以便第一列填充屏幕的三分之二。

<!--  基本网格示例-->
<div class="slds-grid">
  <div class="slds-col slds-size--4-of-6">Column 1</div>
  <div class="slds-col slds-size--1-of-6">Column 2</div>
  <div class="slds-col slds-size--1-of-6">Column 3</div>
</div>

Columns in 4:1:1 width ratio

大小助手也可以用来根据屏幕大小指定不同的布局。例如,让我们创建一个两列网格,其中两列是:

  • 全宽,并垂直排列在手机屏幕上
  • 大小为1:1,并排排列在小屏幕上(> 480像素)
  • 大小为3:1,并排放置在较大的屏幕上(> 768像素)

Responsive example

这里是相应的标记:

<!-- 响应网格示例 -->
<div class="slds-grid slds-wrap">
  <div class="slds-col slds-size--1-of-1 slds-small-size--1-of-2 slds-medium-size--3-of-4">A</div>
  <div class="slds-col slds-size--1-of-1 slds-small-size--1-of-2 slds-medium-size--1-of-4">B</div>
</div>

使用这种移动优先方法,您可以在需要的特定断点处控制元素宽度。没有更多的移动页面破碎!

我们只涉及到网格的基础知识。有关网格的更多文档,请参阅Design System网站上的网格系统和尺寸页面。现在到一些代码!

创建页眉

我们来创建一个列表视图页面。我确信你在Salesforce中看到过他们。以下线框显示了我们的目标:

  • 顶部标题,适当地摆放
  • 主列表区
  • 底部页脚

List view wireframe

使用以下代码创建一个名为Trailhead_SLDS_Listview的新Visualforce页面:

<apex:page showHeader="false" standardStylesheets="false" sidebar="false" applyHtmlTag="false" applyBodyTag="false" docType="html-5.0">

<html xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" lang="en">
<head>
  <meta charset="utf-8" />
  <meta http-equiv="x-ua-compatible" content="ie=edge" />
  <title>Salesforce Lightning Design System Trailhead Module</title>
  <meta name="viewport" content="width=device-width, initial-scale=1" />

  <!-- 导入设计系统样式表 -->
  <apex:slds />
</head>
<body>

  <!-- 需要的SLDS包装 -->
  <div class="slds-scope">

    <!-- MASTHEAD -->
    <p class="slds-text-heading--label slds-m-bottom--small">
      Salesforce Lightning Design System Trailhead Module
    </p>
    <!-- / MASTHEAD -->

    <!-- PAGE HEADER -->
    <!-- / PAGE HEADER -->

    <!-- PRIMARY CONTENT WRAPPER -->
    <div class="myapp">
    </div>
    <!-- / PRIMARY CONTENT WRAPPER -->

    <!-- FOOTER -->
    <!-- / FOOTER -->

  </div>
  <!-- / 需要的SLDS包装 -->

  <!-- JAVASCRIPT -->
  <!-- / JAVASCRIPT -->
</body>
</html>
</apex:page>
这是我们的列表视图页面的骨架大纲。现在我们将通过添加页眉组件来使事情变得更加有趣。这个组件有一堆新的标记和类,但不用担心,我们将在下面进行介绍。用下面的代码替换标记中的<! – PAGE HEADER – >部分:
<!-- PAGE HEADER -->
<div class="slds-page-header" role="banner">
  <div class="slds-grid">
    <div class="slds-col slds-has-flexi-truncate">
      <!-- HEADING AREA -->
      <p class="slds-text-title--caps slds-line-height--reset">Accounts</p>
      <h1 class="slds-page-header__title slds-truncate" title="My Accounts">My Accounts</h1>
      <!-- / HEADING AREA -->
    </div>
    <div class="slds-col slds-no-flex slds-grid slds-align-top">
      <button class="slds-button slds-button--neutral">New Account</button>
    </div>
  </div>
  <div class="slds-grid">
    <div class="slds-col slds-align-bottom slds-p-top--small">
      <p class="slds-text-body--small page-header__info">COUNT items</p>
    </div>
  </div>
</div>
<!-- / PAGE HEADER -->
如果你现在预览你的页面,你会看到列表视图页面开始开始,而且是顶部。现在是问自己一个好时机:“我必须写多少CSS才能创建这个美丽风格的页眉组件?

List view with header complete

由于这是更高级的设计系统组件之一,我们将逐行进行。我们建议您在我们经历的时候,在您最喜欢的开发环境中打开您的源代码:

外部包装器<div>具有应用页面标题样式的类slds-page-header。里面我们有一个两列的Grid System。

第一个网格列包含两个元素,其中一个具有文本标题实用程序类,而另一个具有特定于组件的CSS类slds-page-header__title。

第二栏涉及更多一点。它有多个应用的​​类:slds-col slds-no-flex slds-grid slds-align-top。 slds-no-flex是设计系统布局实用程序类之一,并通过删除其flex属性来防止列自动调整大小。 slds-align-top是一个对齐工具类,用于调整列内容的垂直位置,使其与顶部对齐。

在第二列中,我们有一个Button组件,它有一个修饰符类,slds-button-neutral,它应用最小的样式。

在网格下面,页面标题的第二行是一个简单的占位符,用于列表视图中项目数的计数。

填写列表视图轮廓的其余部分

接下来,我们将添加一个简单的无序列表作为光荣的数据表的即将到来的占位符。用下面的代码替换标记中的<! – PRIMARY CONTENT WRAPPER – >部分:

<!-- PRIMARY CONTENT WRAPPER -->
<div class="myapp">

  <ul class="slds-list--dotted slds-m-top--large">
    <li>Account 1</li>
    <li>Account 2</li>
    <li>Account 3</li>
    <li>Account 4</li>
    <li>Account 5</li>
    <li>Account 6</li>
    <li>Account 7</li>
    <li>Account 8</li>
    <li>Account 9</li>
    <li>Account 10</li>
  </ul>

</div>
<!-- / PRIMARY CONTENT WRAPPER -->
预览页面,你会看到基本的列表视图布局采取的形式:

List view with layout complete

默认情况下,内容将填充屏幕宽度。如果您希望将主要内容在屏幕上水平放置或将其限制在特定宽度,请使用slds-container – * helper类之一。

设计系统样式应用于带有slds-list-dotted和slds-m-top-large类的<ul>。无可否认,这不是很令人兴奋的主要内容,只是等到下一个单位…

让我们暂且放一下。设计系统的重点是作为一个“应用程序框架”,而不是“网页框架”。为此,我们避免在默认情况下添加额外的样式。相反,开发人员可以选择手动添加其他样式,例如在本例中。这使开发人员能够更好地控制确切的布局,并且在空间有限的情况下可以产生很大的影响。在您了解设计系统时,您将会看到很多其他组件(如Button)中的默认样式假设。

要完成我们的列表视图布局框架,我们将使用另一个Grid System组件添加页脚。你现在应该成为这方面的专家!我们使用一些额外的修饰符类:

  • slds-p-around – large为页脚元素添加填充
  • slds-grid – align-spread展开主轴上的网格列,第一列从最左边开始,最后一个结束于最右边。

这里是<! – FOOTER – >评论之间的页脚标记:

<!-- FOOTER -->
<footer role="contentinfo" class="slds-p-around--large">
  <!-- LAYOUT GRID -->
  <div class="slds-grid slds-grid--align-spread">
    <p class="slds-col">Salesforce Lightning Design System Example</p>
    <p class="slds-col">&copy; Your Name Here</p>
  </div>
  <!-- / LAYOUT GRID -->
</footer>
<!-- / FOOTER -->
预览您的页面,您可以看到正在形成的列表视图。再次注意,我们不需要编写任何CSS来给我们提供最新的Lightning UI样式。我们所要做的就是在我们的HTML标记中应用Design System类。在下一个单元中,我们将钩住一些真实的数据。

List view with layout complete

最后一个注意事项:请记住,网格系统可能并不总是实现特定布局的最佳组件。例如,如果您想要并排显示图像和文本,则只需使用“媒体对象”或“拼贴”组件可能会更简单。

Lightning-设计(2)开始

学习目标

完成本单元后,您将能够:

  • 使用Design System设计一个基本的Visualforce页面。
  • 描述设计系统的类结构和块元素修饰符(BEM)语法。

创建一个首页

在本模块其余部分的过程中,我们将使用设计系统构建Visualforce页面。让我们创建第一个Visualforce页面并包含设计系统。然后,我们将通过测试页面来解释设计系统的类结构。

进入安装程序,然后为“页面”快速查找,创建一个Visualforce页面。完成表格如下:

  • 标签: Trailhead_SLDS_Basic
  • 名称: 应该自动默认为 Trailhead_SLDS_Basic
<apex:page showHeader="false" standardStylesheets="false" sidebar="false" applyHtmlTag="false" applyBodyTag="false" docType="html-5.0">

<html xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" lang="en">
<head>
  <meta charset="utf-8" />
  <meta http-equiv="x-ua-compatible" content="ie=edge" />
  <title>Salesforce Lightning Design System Trailhead Module</title>
  <meta name="viewport" content="width=device-width, initial-scale=1" />

  <!-- 导入设计系统样式表-->
  <apex:slds />
</head>
<body>

  <!--  需要的SLDS包装-->
  <div class="slds-scope">

    <!-- MASTHEAD -->
    <p class="slds-text-heading--label slds-m-bottom--small">
      Salesforce Lightning Design System Trailhead Module
    </p>
    <!-- / MASTHEAD -->

    <!-- PRIMARY CONTENT WRAPPER -->
    <div class="myapp">

      <!-- 部分 - 徽章组件 -->
      <section aria-labelledby="badges">
        <h2 id="badges" class="slds-text-heading--large slds-m-vertical--large">Badges</h2>
        <div>
          <span class="slds-badge">Badge</span>
          <span class="slds-badge slds-theme--inverse">Badge</span>
        </div>
      </section>
      <!-- / SECTION - BADGE COMPONENTS -->

    </div>
    <!-- / PRIMARY CONTENT WRAPPER -->

  </div>
  <!-- / 需要的SLDS包装 -->

</body>
</html>
</apex:page>
如果您现在预览您的页面,您应该看到以下内容:

Basic demo page

看起来像新的闪电设计,而不必自己写任何CSS。相当漂亮,是吧?

哦,不要为这些徽章数量太多而感到兴奋。他们是设计系统的组件,而不是Trailhead徽章!我们很乐意帮助你创造自己的,但是Trailhead警察会感到不安。

虽然这个例子非常简单,但它引入了很多设计系统的概念。在进入更多令人兴奋的布局之前,我们会对这些进行评估

与所有Visualforce页面一样,标记的外层包装是<apex:page>元素。

在你的html标签上,一定要包含xmlns =“http://www.w3.org/2000/svg”xmlns:xlink =“http://www.w3.org/1999/xlink”属性。这对于在Visualforce中启用对SVG图标精灵贴图的支持非常重要。注意:我们的示例显示标题,侧栏和内置样式表已关闭。目前,如果您需要使用Salesforce标题或侧栏,则无法在<html>元素上指定额外的属性。在这种情况下,不支持SVG图标。

在我们的<head>部分,我们使用<apex:slds />导入设计系统,它将加载文档中的CSS。

现在进入包含我们的第一个设计系统标记的<body>标签。我们将一行一行地通过它。由于有相当多的事情发生,我们建议在您最喜欢的编辑器中同时打开页面。我们走吧。

每次在Visualforce中使用“设计系统”标记时,都应将其放在具有slds-scope作用域类的外部包装器<div>中。每次。无论您是否拥有Visualforce标题并留下导航,或者不是。得到它了?它会在稍后的测验中。

接下来我们有一个简单的桅杆头标签,其中应用了两个设计系统类。首先,slds-text-heading – 标签应用文本标题样式。第二个类slds-m-bottom-small是一个间隔工具类,用于在标题下添加一些填充。你可能会问这些疯狂的类名是什么?这是双下划线错字?继续阅读,所有将被解释。

在<section>元素中,我们有另一个标题,这次是<h2>,用slds-m-vertical-large spacing工具类来添加顶部和底部填充。

您可能会惊讶于需要明确添加此垂直填充。重要的是要记住,设计系统侧重于应用程序的构建,而不是布置网页。因此,从排版中删除了默认页边距,以便应用程序生成器可以精确地指定他们需要的内容。

最后,我们看到我们的第一个真正的设计系统组件,一个徽章组件。其实有两个,但是谁在计数?每个通过将一个slds-badge类应用到span元素来创建。第二个徽章有一个slds主题 – 逆主题实用程序类,以反转配色方案。请注意如何将多个Design System类应用于同一个元素以逐步自定义它。在这种情况下应用徽章样式,然后反转颜色。稍后你会在模块中看到更多的内容。

这里的所有都是它的!布置你的标记,并应用相应的设计系统类为最新的闪电视觉设计。看马,没有CSS!

所有的设计系统类都记录在设计系统网站上。

Badge documentation

SLDS类命名

在我们继续之前,让我们先谈谈在Design System类名称中提到的那些双连字号。我们的CSS使用一个叫做块元素修饰语法(BEM)的标准类命名约定来使得类名不那么含糊:

  • 块表示高级组件(例如.car)
  • 元素表示组件的后代(例如.car_door)
  • 修饰符表示块或元素的特定状态或变体(例如,车门 – 红色)

现在炙手可热的问题,为什么双连字符和下划线?首先,他们可以更容易地看到CSS规则正在被应用(通过分离出块/元素和修饰符)。而且,使用双精度而不是单个连字符和下划线表示块或修饰符本身可以包含连字符或下划线,例如.slds-button__icon-x-small。给它一个去,我们认为你会发现它一样有用,因为我们一旦你习惯了。

Lightning-设计(1)

学习目标

完成本单元后,您将能够:

  • 描述Salesforce Lightning设计系统是什么以及它的用途。
  • 描述设计系统所依据的关键设计原则。

介绍闪电设计系统

Salesforce用户体验团队一直在努力将Enterprise UX推向21世纪,并为能够提供Lightning设计系统而感到自豪。设计系统使您可以轻松构建符合新Salesforce Lightning外观的应用程序,而无需将UI反向设计为自定义CSS。实际上,使用新的设计系统标记会导致在没有编写任何CSS的情况下具有Lightning外观和感觉的页面。感兴趣吗?激动吗?我们是!阅读。

Lightning Design System website

闪电设计系统是相当的一口,所以我们在这里称之为“设计系统”。

您可能使用了其他类似的设计系统,例如Twitter Bootstrap或Foundation来构建网站。这个设计系统的主要好处是:

  • 它是为构建Salesforce应用程序而量身定制的。使用Design System标记和CSS框架会生成反映Salesforce Lightning外观的UI。关注构建应用程序是一个重要的记住。设计系统不会过度执行诸如填充和边距之类的默认设置,而其他一些框架则专注于构建营销页面。设计系统可让您轻松指定所需的确切布局,同时符合新的Lightning UI。
  • 它不断更新。只要您使用的是最新版本的设计系统,您的页面就会始终与Salesforce UI更新保持同步。
  • 辅助功能被烘焙到组件背后的CSS框架中。
  • CSS完全由slds-前缀命名,并且使用slds-scope类作用域以避免CSS冲突。

设计系统捆绑了四种类型的资源来帮助您构建应用程序。

  • CSS framework — 定义UI组件,例如页面标题,标签和表单元素,网格布局系统和单一用途的帮助程序类,以帮助进行间距,大小调整和其他视觉调整。
  • Icons — 包括我们的动作,自定义,文档类型,标准和实用程序图标的PNG和SVG(包括个人和spritemap)版本。
  • Font — 印刷术是我们产品的核心。我们从头开始设计了全新的Salesforce Sans字体,为我们的产品提供独特的视觉语音和个性,并将其作为设计系统的一部分提供给您。
  • Design Tokens — 这些设计变量允许您调整视觉设计的各个方面以匹配您的品牌。可定制的变量包括颜色,字体,间距和大小。

设计系统围绕现代浏览器的功能而构建,并具有一些最低限度的浏览器要求。 Chrome,Safari和Firefox的现代版本已经过全面测试。对于Microsoft Internet Explorer(MSIE),Design System仅支持版本11和Microsoft Edge。早期版本的MSIE的用户可能会遇到诸如缺少图标等问题。

核心设计原则

设计系统代表的Lightning Experience UI是使用四个核心设计原则制作的。我们鼓励您在开发应用程序时记住它们。

  • 清晰 —消除歧义。使人们有信心地看到,理解和行动。新的用户界面减少了混乱,使用户可以很容易地找到他们需要的信息。
  • 效率— 简化和优化工作流程。智能地预测需要帮助人们更好,更聪明,更快地工作。例如,新的Lightning用户界面按钮可以改善行动号召力。
  • 一致性 — 通过对相同的问题应用相同的解决方案,创造熟悉性并增强直觉。例如,新UI在所有上下文中强制执行一个按钮样式。
  • 美丽 — 通过周到和优雅​​的工艺,展现对人们时间和关注的尊重。一个UI可以美丽吗?我们这么认为!

你可以在哪里使用设计系统

新的设计系统使得在一系列技术堆栈中构建符合Lightning的Salesforce应用程序变得简单易行。

  • Visualforce pages 通过远程对象或JavaScript远程访问来访问Salesforce数据。设计系统还不兼容<apex>标签,但请留意这个空间。
  • Lightning pages and components 可用于Salesforce1和Lightning Experience
  • Mobile apps 通过Mobile SDK或其他API访问Salesforce
  • Standalone web apps Heroku或类似平台提供

模块先决条件

该模块的其余部分包括一些有趣的手动技术工作。在您进入之前,请查看以下先决条件:

  • 您必须有权访问Salesforce开发者帐户。
  • 示例页面假设您具有Web开发(HTML,CSS,JavaScript)和Salesforce管理的一些知识。
  • 该模块着重于使用Visualforce页面中的设计系统,因此有一定的技术经验是有益的。 但是,尽管代码示例是特定于Visualforce的,但您可以在其他堆栈中重复使用它们,但只需进行较小的自定义操作。

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代码去做!即使你是一个性格开朗的开发者,也会觉得非常神奇。接下来,让我们完成我们设定的操作并覆盖“新建”按钮。

Lightning-覆盖标准按钮(2)

通常,当我们考虑Lightning组件时,我们会考虑Lightning Experience中页面上的元素。换句话说,我们想到了前端设计 – 用户在页面上的交互。但是我们也可以构建根本没有任何前端标记的Lightning组件。但是你可能在想,为什么有人会那样做呢?因为我们也可以使用Lightning组件作为可重用的服务或服务组件。

在这一步结束之后,您将会:

  • 了解服务组件的概念
  • 检索选项列表值列表
  • 传递两个组件之间的值

创建闪电组件

  1. 在开发者控制台中,选择 File > New > Lightning Component.
  2. 对于名称,输入: PickListValues 并单击 Submit.

    请注意,我们没有检查任何框,因为我们不打算将这个组件作为一个独立的组件在页面上使用。相反,我们将其用作PropertyDialog组件的子组件,或者将其用作需要选项列表值的任何其他组件的子项。

  3. 将以下内容添加到<aura:component>标记内的组件中:
    <aura:attribute name="sObjectName" type="String" />
    <aura:attribute name="fieldName" type="String" />
    <aura:attribute name="picklistValues" type="Object" />
    
    因为这是一个服务组件,它唯一要做的就是存储一些值。在我们的情况下,我们想知道状态选项列表的值。我们将把它们作为值存储在<aura:attribute name =“picklistValues”/>中。
  4. 保存文件。

检索选项列表值

  1. 在开发者控制台中,点击 File > New > Apex Class.
  2. 命名类: PickListController
  3. 将以下内容添加到 class:
    @AuraEnabled        
    public static List<String> getPickListValuesIntoList(String objectType, String selectedField){
        List<String> pickListValuesList = new List<String>();
        Schema.SObjectType convertToObj = Schema.getGlobalDescribe().get(objectType);
        Schema.DescribeSObjectResult res = convertToObj.getDescribe();
        Schema.DescribeFieldResult fieldResult = res.fields.getMap().get(selectedField).getDescribe();
        List<Schema.PicklistEntry> ple = fieldResult.getPicklistValues();
        for( Schema.PicklistEntry pickListVal : ple){
            pickListValuesList.add(pickListVal.getLabel());
        }     
        return pickListValuesList;
    }
    
    我们称之为Lightning组件的Apex方法,我们需要使用@AuraEnabled和静态签名。 getPickListValuesIntoList方法接受两个参数,objectType和selectedField。我们将ObjectType变量作为String传递,所以我们把String转换成Object,然后得到它的字段列表。然后我们检索选取列表值,为每个值添加标签,最后返回列表。
  4. 保存文件。

把它连接起来

  1. 在开发者控制台中,切换回PickListValues组件。
  2. 将controller =“PickListController”access =“global”添加到<aura:component>标记。
  3. 在aura属性之后的新行中,将以下内容添加到组件中:
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
    
  4. 保存文件。
  5. 单击侧面导航中的“控制器”以将控制器添加到组件。
  6. 将控制器中的代码替换为:
    ({
        doInit : function(component) {
            var action = component.get("c.getPickListValuesIntoList");
            action.setParams({
                objectType: component.get("v.sObjectName"),
                selectedField: component.get("v.fieldName")
            });
            action.setCallback(this, function(response) {
                var list = response.getReturnValue();
                component.set("v.picklistValues", list);
            })
            $A.enqueueAction(action);
        }
    })
    

    这个非常简单的函数调用我们刚刚创建的Apex类的getPickListValuesIntoList方法,然后将它们存储在picklistValues属性中。

  7. 保存文件。

添加服务组件

  1. 在Developer Console中,切换到PropertyDialog组件。
  2. 在打开<aura:component>标记之后添加对PickListValues组件的引用:
    <aura:attribute name="picklistValues" type="Object" />
    <c:PicklistValues sObjectName="Property__c" fieldName="Status__c" picklistValues="{!v.picklistValues}" />
    
    当我们向另一个Lightning组件添加一个子组件时,我们也可以设置子组件中包含的属性。这些值可以是显式定义的,就像我们在这里做的那样,或者是根据绑定到父组件的属性来动态分配的。当Apex类返回值时,我们在子组件中设置picklistValues属性。然后,这个值将起泡到<c:PicklistValues>上的属性定义,该属性定义依次在父组件中设置。啊,数据绑定的美丽!
  3. 将<lightning:select>中的<option value =“status”> Status </ option>替换为:
    <aura:iteration items="{!v.picklistValues}" var="item">
        <option value="{!item}">{!item}</option>
    </aura:iteration>
    
    现在,将使用picklistValues属性中的条目来动态填充<lightning:select>。
  4. 保存该文件,然后刷新组织中的属性记录页面。

    如果一切顺利,而不是“状态”一词,正确的值显示在您的状态选项列表中。

    做得好! 现在我们需要做的就是连接组件,以便能够保存新的属性记录。

Lightning-覆盖标准按钮(1)

介绍

在这个项目中,我们将介绍创建Lightning组件的过程,以便用作标准操作的重写。

在这个过程中,我们将完成以下工作:

  • 创建一个闪电组件。
  • 构建一个服务组件。
  • 利用闪电数据服务来创建和编辑记录。
  • 调查使用Lightning组件作为覆盖的含义。
  • 使闪电组件具有上下文感知能力。

听起来很有趣?让我们开始吧!

安装Trailhead包并导入数据

我们要做的第一件事就是在Trailhead Playground中安装一个软件包,里面包含我们在这个项目中工作的应用程序和代码。

  1. 将此Trailhead项目包安装到Trailhead游乐场。检查URL以确保您正在安装到正确的组织中。您需要您的动手组织用户名和密码才能安装此软件包。如果您正在使用Trailhead Playground,本文将向您介绍如何找到您的用户名并重置您的密码。如果您在AppExchange中安装软件包或应用程序时遇到问题,请按照本文中的步骤操作。
  2. 安装软件包后,点击alt text:App Launcher图标alt text: App Launcher icon,选择Dreamhouse Lightning。
  3. 单击数据导入,然后初始化示例数据。这将导入您在此项目中使用的数据。
  4. 点击设置图标alt text: Setup Icon,然后选择设置。
  5. 在快速查找框中输入会话并选择会话设置。
  6. 滚动到“缓存”部分,取消选中 Enable secure and persistent browser caching to improve performance.
  7. 点击 Save.
  8. 如果您正在使用Trailhead Playground进行此项目,那么您已经全部准备好了!如果您在此项目中使用开发人员版组织,请按照以下步骤打开“我的域”。

创建一个闪电组件

在这个项目中,我们修改了我们为DreamHouse Realty(一家位于波士顿的房地产公司)建造的DreamHouse应用程序。 DreamHouse Realty使用这个应用程序来管理房屋,经纪人和潜在客户的库存。每个属性记录包含近20个字段,其中大多数在标准的“创建属性”对话框中表示。我们已经被要求简化创建财产记录的过程,通过覆盖标准的新建按钮,并显示一个简单的形式只有少数必要的领域。

没问题!我们走吧。

  1. 点击 alt text: App Launcher icon 选择Dreamhouse
  2. 点击 Properties.
  3. 点击 New.

    这是我们要覆盖的形式。对于我们的新形式,我们只打算使用名称字段,其实际上是地址,价格,卧室和浴室的数量以及状态。

  4. 点击 Cancel.
  5. 点击 alt text: Setup Icon 然后选择开发者控制台。
  6. 在开发者控制台中,选择 File > New > Lightning Component.
  7. 给组件一个PropertyDialog的名字。
  8. 在组件配置下,选择Lightning Record Page 然后单击 Submit.

    你想知道为什么我们为这个组件选择闪电记录页吗?那么即使我们打算使用这个组件作为重写,在开发过程中,将它添加到页面上会很有帮助,以便我们可以在构建它时看到它。大。现在让我们继续创建表单。

创建一个表单

  1. 在您的新组件中,在<aura:component>标签之间添加以下内容:
    <lightning:input aura:id="propName" name="propName" label="Property Name" required="true" />
    <lightning:input aura:id="propBeds" name="propBeds" label="Beds" />
    <lightning:input aura:id="propBaths" name="propBaths" label="Baths" />
    <lightning:input aura:id="propPrice" name="propPrice" label="Price" />
    <lightning:select aura:id="propStatus" name="propStatus" label="Status">
            <option value="status">Status</option>
    </lightning:select>
    <lightning:button variant="neutral" label="Cancel" />
    <lightning:button variant="brand" label="Submit" />
    
    Base Lightning组件在17年冬季首次推出,每次发布都增加更多。使用它们来构建Lightning组件的最酷的事情之一是他们处理Salesforce闪电设计系统(SLDS)为我们创建相应的HTML和CSS。名称字段是属性记录中唯一必需的字段。因此,Name的输入使用required =“true”属性。您还可以为<lightning:input>指定一个类型,例如数字,电子邮件或密码。有关可能的类型的完整列表,请参阅“Lightning组件开发人员指南”。
  2. 单击 File > Save 以保存组件。
  3. 切换回您的组织并单击 Properties.
  4. 点击任何属性名称以导航到其属性记录页面。
  5. 点击 alt text: Setup Icon然后选择 Edit Page.
  6. 在Lightning App Builder中,将PropertyDialog组件拖动到页面上,并将其放置在右侧列的顶部。

    放置组件的位置并不重要,因为我们只把它放在一个页面上,以便在开发过程中看到它。当我们准备使用它作为覆盖时,我们从页面中删除它。

  7. 点击 Save.
  8. 通过单击激活,应用程序默认值,然后指定为应用程序默认值来激活页面。 选择Dreamhouse Lightning作为应用程序,然后单击下一步,然后单击保存。
  9. 点击返回以退出App Builder。

alt text: Property record page with the Property Dialog component added.

你开始一个伟大的开始! 但可悲的是,你的形式并没有做任何事情,也不是很好。 我们需要把它连接起来,这样它可以保存一个新的记录和修复样式,但在我们做之前,我们需要解决状态选择列表。

Lightning-应用程序(6)

在Visualforce页面中使用Lightning组件

到目前为止,您已经学会了如何使您的Visualforce页面看起来像Lightning Experience,并学习了创建Lightning组件的基础知识。你甚至已经创建了一个很棒的Similar Properties组件。

但是还有最后一件事情要完成,这真是太神奇了。

我们将采用类似的属性组件,并在Visualforce中使用它!是的,你没看错。闪电组件不仅仅是闪电体验。使用闪电,我们可以在任何地方使用闪电组件!

第1部分 – 创建容器应用程序

要在Lightning体验外使用Lightning组件,我们需要将其封装在Lightning应用程序中。闪电应用程序基本上是一个闪电组件,它运行在自己的窗口中,没有典型的Lightning Experience UI(例如全局导航)。事实上,在这个项目中,您已经多次使用了Lightning应用程序。闪电应用程序生成器是一个闪电应用程序!

  1. 在开发者控制台中,点击 New > Lightning Application. 将其命名为SimilarPropertiesApp并选择Lightning Out Dependency App。

    通过选择Lightning Out Dependency App,应用程序实现extends =“ltng:outApp”,它基本上告诉App使用Lightning Out框架。

  2. 为组成SimilarProperties组件的三个组件中的每个组件添加一个依赖关系 – 用以下代码替换缺省代码:
    <aura:application extends="ltng:outApp" >
        <aura:dependency resource="c:SimilarProperties" />
      <aura:dependency resource="c:SimilarProperty" />
        <aura:dependency resource="c:SimilarPropertyEdit" />
        <aura:dependency resource="markup://force:*" type="EVENT"/>
    </aura:application>
    

    我们基本上告诉Lightning应用程序,我们将使用这些Lightning组件。即使其他组件仅包含在SimilarProperties组件中,也包含所有组件。

    我们将该组件添加到Visualforce页面,所以我们需要确保当用户点击属性名称时,我们正在正确处理该记录的导航。这意味着我们需要检测组件是在Lightning Experience页面上使用,正在Lightning Experience中显示的Visualforce页面中使用,还是在Salesforce Classic中的Visualforce页面中使用。

    最后的依赖包括force:namespace中的事件,例如导航事件。当Lightning组件在Lightning Experience中运行时,它将自动访问这些事件。所以我们不必为了在navToRecord函数中调用$ A.get(“e.force:navigateToSObject”)而做任何事情。在Lightning Experience的Visualforce页面中运行的Lightning组件也可以访问这些事件,但语法略有不同。但是,在Salesforce Classic的Visualforce页面中运行Lightning组件时,我们必须使用完全不同的方法来执行导航等操作。

  3. 保存文件。

第2部分 – 更新Visualforce页面

由于我们已经有一个嵌入在Property Record页面中的Visualforce页面,所以我们可以更新标记来使用Similar Properties组件。

  1. 在开发人员控制台中,选择 File > Open Resource, 然后打开“Similar_Properties.vfp”页面。
  2. 更新页面如下:
    <apex:page standardController="Property__c" standardStylesheets="false" applyBodyTag="false">
    
        <style>
            html, body {
            margin: 0;
            padding: 0;
            }
            #lightningComponent {width: 100%;}
        </style>
    
        <div id="content">
            <div id="lightningComponent" />
        </div>
    
    </apex:page>
    
    不要恐慌,但是,你基本上只是摧毁了页面。没关系,因为页面只包含Lightning组件,我们将把这个组件放在带有lightningComponent的id的<div>中。

第3部分 – 在Visualforce页面中加载SimilarProperties组件

  1. 在打开的<apex:page>标签之后立即添加<apex:includeLightning />标签。

    该指令在页面中包含Lightning Out框架。

  2. 在关闭</ apex:page>标记之前立即添加以下JavaScript代码:
    <script>
    var recordId = '{!Property__c.Id}';
    var myUserContext = "{!$User.UITheme}";
    $Lightning.use("c:SimilarPropertiesApp", function() {
        $Lightning.createComponent("c:SimilarProperties",
                                   {recordId: recordId},
                                   "lightningComponent",
                                   function(cmp) {
                                       $A.eventService.addHandler({
                                           event: 'force:navigateToSObject',
                                           handler: function(event) {
                                               if (myUserContext == 'Theme4t' || myUserContext == 'Theme4d') {
                                                   // Visualforce页面位于S1或Lightning Experience中
                                                   sforce.one.navigateToSObject(event.getParams().recordId);
                                               } else if (myUserContext == 'Theme3') {
                                                   // Visualforce页面正在Classic中运行
                                                   window.parent.location = '/' + event.getParams().recordId;
                                               } else {
                                                   console.log("Unsupported theme");   
                                               }
                                           }
                                       });
                                   }
                                  );
    });
    </script>
    

    这是魔术发生的地方!该脚本从标准控制器中检索记录的Id并获取用户的主题,并将其分配给变量。然后$ Lightning.use()指示页面包含您刚刚创建的SimilarPropertiesApp。然后在应用程序中创建SimilarProperties组件的一个实例,将recordId传递给组件,然后将它放在页面中具有lightningComponent的id的<div>中。

    最后,在创建组件之后,我们添加了一个事件处理程序$ A.eventService.addHandler,并将force:navigateToSObject事件声明为我们有兴趣监听的事件。当用户点击组件中的一个Property Name时,脚本拦截对$ A.get(“e.force:navigateToSObject”)的调用并执行定义为该处理程序的函数。这个函数使用脚本第二行定义的myUserContext变量来检测用户的主题。如果用户的主题是Theme4t(Salesforce1)或Theme4d(Lightning Experience),则脚本将使用在Lightning Experience内的Visualforce页面中运行的Lightning Component的正确语法来触发navigateToSObject方法。如果用户的主题是Theme3,则我们知道Classic中的用户,并使用window.parent.location指示页面导航到新页面。

  3. 保存文件。
  4. 刷新“属性记录”页面并向下滚动到“类似属性”部分以查看组件。
    雷电体验类似的属性部分。

    Similar Properties section in Lightning Experience.

    多么酷啊?这是Lightning页面中Visualforce页面中的闪电组件。这是一个Salesforce Turducken!

  5. 单击组件中的“属性名称”以确认导航正在工作。
  6. 点击您的个人资料图片,然后选择切换到Salesforce Classic。
  7. 在最近的项目列表中点击一个属性。
  8. 向下滚动以查看在Salesforce Classic中运行的美丽的Lightning组件!
    Similar Properties section in Salesforce Classic.
  9. 单击组件中的不同Property Name,然后使用脚本中的window.location方法导航到正确的记录。
  10. 点击你的名字,然后选择切换 Switch back to Lightning Experience.

    轻拍自己的背部!您不仅创建了令人惊叹的Lightning组件,还了解了在Visualforce中利用Lightning组件的轻松方式,无论您是在Lightning Experience中还是在Salesforce Classic中使用Visualforce页面。接下来的步骤中,您可能需要编辑页面布局编辑器中的页面布局,以使Visualforce页面的空间更高一些。但是我们会把这个留给你。现在是时候吹嘘一下,去展示你的同事们!

Lightning-应用程序(5)

创建一个类似的属性闪电组件

现在,您已经成功地掌握了Lightning组件的基础知识,现在是时候认真思考并构建一个真正有用的工具。我们将利用我们的知识,并使用Lightning组件替换VisualConfiguration类似的页面,它可以做同样的事情 – 还有更多!当你完成时,你会有一个闪电组件:

  • 根据Salesforce Admin定义的搜索条件检索并显示数据。
  • 使用系统事件导航到记录。
  • 对记录上的CRUD操作使用force:recordData。
  • 公开在App Builder中使用的设计参数。

第1部分 – 创建Apex类控制器

显然,我们的组件将需要来自Salesforce的数据,就像我们用这个组件替换的Visualforce页面一样。但是,Visualforce页面只能用硬编码的条件返回属性。我们的组件将(最终)允许我们的Salesforce Admin通过在组件添加到页面时定义搜索条件来确定要搜索的内容。所以让我们通过创建一个新的Apex类来接受搜索条件。

  1. 在开发人员控制台中,选择 File > New > Apex Class. 命名类MyPropertyController,然后单击确定。
  2. 将默认代码替换为:
    public with sharing class MyPropertyController {
        @AuraEnabled
        public static List<Property__c> getSimilarProperties (Id recordId, String searchCriteria, Decimal beds, Decimal price, Decimal priceRange ) {
             if (searchCriteria == 'Bedrooms') {
                 return [
                     SELECT Id, Name, Beds__c, Baths__c, Price__c, Broker__c, Status__c, Thumbnail__c
                     FROM Property__c WHERE Id != :recordId AND Beds__c = :beds
                 ];
             } else {
                 Decimal range;
                 if (priceRange == null) {
                     range = 100000;
                 } else {
                     range = priceRange;
                 }
                 return [
                     SELECT Id, Name, Beds__c, Baths__c, Price__c, Broker__c, Status__c, Thumbnail__c
                     FROM Property__c WHERE Id != :recordId AND Price__c > :price - range AND Price__c < :price + range
                 ];
             }
         }
    }
    
    您将已经识别出@AuraEnabled和静态签名,以便我们的Lightning组件可以调用getSimilarProperties方法。这个方法有四个参数:recordId,searchCriteria,床位和价格。 recordId将用于当前的Property记录。然后,该方法使用参数根据searchCriteria是否为Bedrooms来选择相似的属性。
  3. 保存文件并关闭其在开发者控制台中的标签。

第2部分 – 创建类似的属性组件

  1. 在开发者控制台中,选择File > New > Lightning Component.
  2. 命名组件SimilarProperties,选择 Lightning Record Page, 然后单击 Submit.
  3. 将d controller="MyPropertyController" 添加到 <aura:component> 标记中。

    就像我们在HelloWorld组件中指定的那样,我们将组件指向我们刚刚创建的Apex类。

  4. 将以下代码粘贴到<aura:component>标签内的新组件中:
    <aura:attribute name="recordId" type="Id" />
    <aura:attribute name="similarProperties" type="Object[]" />
    <aura:attribute name="property" type="Property__c" />
    <aura:attribute name="remoteRecordId" type="Id" />
    <aura:attribute name="showDialog" type="String" default="false" />
    
    <force:recordData aura:id="propertyService"
                      recordId="{!v.recordId}"
                      targetRecord="{!v.property}"
                      recordUpdated="{!c.doInit}"
                      layoutType="FULL" />
    
    <lightning:card iconName="custom:custom85" title="Similar Properties">
        <div class="slds-p-left_medium slds-p-right_medium">
            <ul class="slds-list_vertical slds-has-dividers_top-space">
                <aura:iteration items="{!v.similarProperties}" var="item" indexVar="i">
                    <li class="slds-list__item">                   
                        {!item.Name}
                    </li>
                </aura:iteration>
            </ul>
        </div>
    </lightning:card>
    

    只有几行代码就有很多事情要做。你会注意到的第一件事是三个<aura:attribute>声明。因为我们选择了Lightning Record Page,所以组件还使用force:hasRecordId接口,该接口将自动检索当前Record页面的Id并将其存储在名为recordId的<aura:attribute>中。

    接下来,我们有一个名为similarProperties的属性,用于存储由Apex类返回的属性。这将采取JSON的形式,所以它的类型被设置为Object []。

    Summer 17发布的新功能之前在Developer Preview中名为force:recordPreview现在已经进入Beta版,并已重命名为<force:recordData>。 force:recordData自动检索由其recordId属性指定的记录,然后将该数据存储在由targetRecord属性定义的<aura:attribute>中。然后,force:recordData开始监听页面上其他组件所做更改,当它检测到更改时,它会触发由recordUpdated属性定义的JavaScript函数。

    该组件的UI由另一个名为<lightning:card>的基本闪电组件组成。该卡使用名为custom85的SLDS中的图标。惊喜,这是一个房地产标志!在卡的主体中,您会注意到一个包含列表项<li>的无序列表<ul>。该组件使用<aura:iteration>遍历类似属性属性中的记录,对于每个记录,它显示属性的名称{!item.Name}。

    最后,当组件加载时,它将recordId分配给force:recordData,然后像我们在HelloWorld组件中一样触发doInit函数。所以,我们需要创建这个功能。

  5. 点击开发者控制台右侧栏中的CONTROLLER。
  6. 用以下代码替换默认代码:
    ({
        doInit : function(component, event, helper) {
            var action = component.get("c.getSimilarProperties");
            action.setParams({
                recordId: component.get("v.recordId"),
                beds: component.get("v.property.fields.Beds__c.value"),
                price: component.get("v.property.fields.Price__c.value")
            });
            action.setCallback(this, function(response){
                var similarProperties = response.getReturnValue();
                component.set("v.similarProperties", similarProperties);
            });
            $A.enqueueAction(action);
        }
    })
    
    doInit函数应该看起来很熟悉,因为您已经在HelloWorld组件中看到了很多代码。新的部分是action.setParams部分。这就是我们如何传递参数给被调用的方法,在这种情况下是getSimilarProperties。当<force:recordData>将其记录存储在targetRecord属性中时,它将以ATTRIBUTE_NAME.fields.FIELD_NAME.value的格式存储它。
  7. 保存文件。
  8. 返回到“属性记录”页面,单击“设置Setup icon”图标并选择“编辑页面”。
  9. 找到定制组件下的SimilarProperties组件,并将其拖到右侧列顶部的页面上。
  10. 点击保存,然后点击返回。

    该页面现在应该显示相似的属性(相同价格范围内的属性列表)。

Screenshot of the SimilarProperties Lightning Comopnent.

现在让我们玩一下。

  1. 双击属性记录的价格进行编辑。
  2. 降价约$ 50,000,然后点击保存按钮。
    请注意,组件根据价格变化重新加载。如果你没有得到任何新的物业,再次改变价格。换句话说,force:recordData注意到价格变化并触发了它的recordUpdated函数,它在加载时调用的doInit函数。

第3部分 – 改进用户界面

在构建Lightning组件时,显然我们可以将所有标记放在一个组件中。但是,更好的做法是把事情分解成更小的组件,以包含在较大的组件中。这意味着这些子组件也可以用在其他组件中。

对于这一步,我们将创建一个组件来显示每条记录的更多信息。

  1. 在开发者控制台中,选择 File > New > Lightning Component.
  2. 将该组件命名为SimilarProperty,并取消选中所有复选框。
  3. 将默认标记替换为以下内容:
    <aura:component>
        <aura:attribute name="propertyId" type="Id" />
        <aura:attribute name="targetFields" type="Property__c" />
        <aura:attribute name="showDialog" type="String" />
        <aura:attribute name="remoteRecordId" type="Id" />
    
        <force:recordData aura:id="propertyRecord"
                          recordId="{!v.propertyId}"
                          targetFields="{!v.targetFields}"
                          fields="Name, Beds__c, Baths__c, Price__c, Status__c, Thumbnail__c"
                          />
    
        <div class="slds-media">
            <div class="slds-media__figure">
                <img src="{!v.targetFields.Thumbnail__c}" class="slds-avatar_large slds-avatar_circle" alt="{!v.targetFields.Title_c}" />
            </div>
            <div class="slds-media__body">
                <div class="slds-grid">
                    <a onclick="{!c.navToRecord}">
                        <h3 class="slds-text-heading_small slds-m-bottom_xx-small">{!v.targetFields.Name}</h3>
                    </a>
                    <!-- Edit button goes here -->
                </div>
                <div aura:id="propertyDetails" class="slds-m-top_small">
                    <ul class="slds-grid slds-wrap">
                        <li class="slds-list__item slds-size_1-of-2"><span class="slds-text-color_weak slds-m-right_small">Beds:</span> {!v.targetFields.Beds__c}</li>
                        <li class="slds-list__item slds-size_1-of-2"><span class="slds-text-color_weak slds-m-right_small">Baths:</span> {!v.targetFields.Baths__c}</li>
                        <li class="slds-list__item slds-size_1-of-2"><span class="slds-text-color_weak slds-m-right_small">Price:</span> {!v.targetFields.Price__c}</li>
                        <li class="slds-list__item slds-size_1-of-2"><span class="slds-text-color_weak slds-m-right_small">Status:</span> {!v.targetFields.Status__c}</li>
                    </ul>
                </div>
            </div>
        </div>
    </aura:component>
    
    这个组件有几个<aura:attributes>,但是让我们从<force:recordData>对象开始。这个<force:recordData>看起来和我们主要组件中的一样,但是不是使用layoutType =“FULL”来获取对象的所有字段,现在我们只定义了我们感兴趣的字段字段属性。数据本身存储在targetFields属性中,我们用它来显示<li>元素中的数据。使用targetFields,更容易引用该字段的值。您只需使用格式targetFields.field_name而不是ATTRIBUTE_NAME.fields.FIELD_NAME.value。

    注意这个组件没有init事件处理程序。这是因为记录正在被<force:recordData>对象检索。

  4. 保存文件。
  5. 回到SimilarProperties.cmp组件。将<li>中的{!item.Name}替换为:
    <c:SimilarProperty propertyId="{!item.Id}" remoteRecordId="{!v.remoteRecordId}" showDialog="{!v.showDialog}" />
    
    在另一个组件中嵌入组件时,还可以设置该组件中任何<aura:attribute>的值。在这种情况下,正在设置<force:recordData>对象使用的propertyId,以及稍后将使用的一些属性。
  6. 保存文件。
  7. 返回到“财产记录详细信息”页面并刷新它。

Screenshot of the SimilarProperty Lightning Component revised.

其网格系统是SLDS非常酷的功能之一。看看床,浴场,价格和状态如何很好地排队?这是因为他们正在使用内置到SLDS的网格 – 由具有slds-grid类的任何元素指示。网格包含12列,您只需定义项目的大小和列数。对于这个组件,网格中的每个项目都有一个slds-size_1-of-2的类别,它转化为水平空间的50%。

第4部分 – 导航到一个类似的属性

在SimilarProperty组件中,地址(存储在名称字段中)是一个可点击的链接。 <a>元素有一个触发navToRecord函数的onclick事件。

  1. 在Developer Console中打开SimilarProperty组件。
  2. 点击CONTROLLER并将占位符代码替换为:
    ({
        navToRecord : function (component, event, helper) {
            var navEvt = $A.get("e.force:navigateToSObject");
            navEvt.setParams({
                "recordId": component.get("v.propertyId")
            });
            navEvt.fire();
        }
    })
    
    This is a very straightforward function. It simply declares a variable that instructs the Lightning Framework, that’s the $A, to call the e.force:navigateToSObject event. The Id of the property is passed as a parameter of the event.
  3. 保存文件。
  4. 返回到“属性记录详细信息”页面并刷新它。在“类似属性”组件中,单击属性的名称以导航到该属性记录页面。

第5部分 – 编辑类似的属性“到位”

我们将添加到组件的最后一点功能是允许用户在相似的属性列表中编辑其中一个属性,而无需实际导航到它。

  1. 在开发者控制台中,返回到SimilarProperty组件标记。
  2. 用下面的代码替换 <!-- Edit button goes here -->
    <lightning:buttonIcon iconName="utility:edit" class="slds-col_bump-left" variant="bare" alternativeText="Edit Record" onclick="{!c.editRecord}" />
    
    另一个基本闪电组件<lightning:buttonIcon>允许我们使用一个图标作为按钮。在这种情况下,它将使用SLDS图标实用程序部分的编辑图标,这是一支铅笔。当用户点击按钮时,editRecord函数将会触发。
  3. 保存文件。
  4. 在侧边栏中点击CONTROLLER,然后添加以下功能(再次注意添加一个逗号来分隔功能):
    editRecord : function(component, event, helper) {
        var editRecordEvent = $A.get("e.force:editRecord");
        editRecordEvent.setParams({
            "recordId": component.get("v.propertyId")
        });
        editRecordEvent.fire();
    }
    
  5. 保存文件。
  6. 返回到“财产记录”页面并刷新它。
    Screenshot of editing in place.
  7. 在“类似属性”组件中,单击属性的编辑图标以便就地编辑该属性。

    将编辑保存到记录后,注意它在组件中更新,因为<force:recordData>对象正在监视记录的更改。

第6部分 – 创建一个自定义编辑表单

组件真的开始聚集在一起,但是我们将对用户编辑远程记录时显示的字段进行小小的更改。由于我们只在闪电组件中显示几个字段,因此我们只会在编辑器窗体中显示这些相同的字段。

  1. 在开发者控制台中,创建一个名为SimilarPropertyEdit的新Lightning组件。再次,不要选中所有的框。
  2. 用下列内容替换组件的内容:
    <aura:component>
        <aura:attribute name="showDialog" type="String" default="false" />
        <aura:attribute name="remoteRecordId" type="Id" />
        <aura:attribute name="selectedProperty" type="Property__c" />
        <aura:handler name="change" value="{!v.showDialog}" action="{!c.toggleDialog}" />
        <aura:handler name="change" value="{!v.remoteRecordId}" action="{!c.getRecord}" />
    
        <force:recordData aura:id="editRecord"
                             targetRecord="{!v.selectedProperty}"
                             fields="Id,Name,Beds__c,Baths__c,Price__c,Status__c"
                             mode="EDIT" />
    
        <div aura:id="editDialog" role="dialog" tabindex="-1" aria-labelledby="header43" class="slds-modal">
            <div class="slds-modal__container">
                <div class="slds-modal__header">
                    <button class="slds-button slds-modal__close " title="Close" onclick="{!c.toggleDialog}">
                        <lightning:icon iconName="utility:close" variant="bare" ></lightning:icon>
                        <span class="slds-assistive-text">Close</span>
                    </button>
                    <h2 class="slds-text-heading_medium">Edit Record</h2>
                </div>
                <div class="slds-modal__content slds-p-around_medium slds-grid slds-wrap slds-grid_align-spread">
                    <lightning:input aura:id="propName" name="propName" label="Property Name" required="true" value="{!v.selectedProperty.fields.Name.value}" class="slds-size_1-of-1 slds-p-horizontal_x-small" />
                    <lightning:input aura:id="propBeds" name="propBeds" type="number" label="Beds" value="{!v.selectedProperty.fields.Beds__c.value}" class="slds-size_1-of-2 slds-p-horizontal_x-small" />
                    <lightning:input aura:id="propBaths" name="propBaths" type="number" label="Baths" value="{!v.selectedProperty.fields.Baths__c.value}" class="slds-size_1-of-2 slds-p-horizontal_x-small" />
                    <lightning:input aura:id="propPrice" name="propPrice" type="number" label="Price" value="{!v.selectedProperty.fields.Price__c.value}" class="slds-size_1-of-2 slds-p-horizontal_x-small" />
                    <lightning:input aura:id="propStatus" name="propStatus" label="Status" value="{!v.selectedProperty.fields.Status__c.value}" class="slds-size_1-of-2 slds-p-horizontal_x-small" />
                </div>
                <div class="slds-modal__footer">
                    <button class="slds-button slds-button_neutral" onclick="{!c.toggleDialog}">Cancel</button>
                    <button class="slds-button slds-button_brand" onclick="{!c.saveRecord}">Save</button>
                </div>
            </div>
        </div>
        <div aura:id="overlay" class="slds-backdrop"></div>
    </aura:component>
    
    此组件的标记使用SLDS中的模式。而且,正如您以前所见,<force:recordData>正在检索我们希望能够编辑的字段。但是这个<force:recordData>的实例有两个不同之处。第一个区别是没有定义recordId属性。我们将根据用户选择的记录来动态分配该值。其次,该实例将其模式属性设置为EDIT。这使实例能够更新记录。该组件没有init处理程序,而是使用更改处理程序来监视remoteRecordId属性的更改。

    每个按钮都有一个onclick处理函数,我们需要为其编写函数。

  3. 点击CONTROLLER并将占位符代码替换为:
    ({
        getRecord : function(component) {
            var tempRec = component.find("editRecord");
            tempRec.set("v.recordId", component.get("v.remoteRecordId"));
            tempRec.reloadRecord();
        },
        toggleDialog : function(component, event, helper) {
            helper.showHideModal(component);
        },
        saveRecord : function(component,event,helper) {
            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.selectedProperty.fields.Beds__c.value", propBeds);
            component.set("v.selectedProperty.fields.Baths__c.value", propBaths);
            component.set("v.selectedProperty.fields.Price__c.value", propPrice);
    
            var tempRec = component.find("editRecord");
            tempRec.saveRecord($A.getCallback(function(result){
                console.log(result.state);
                if (result.state === "SUCCESS" || result.state === "DRAFT") {
                    var event = $A.get("e.c:recordUpdated");
                    event.fire();
                } else if (result.state === "ERROR") {
                    console.log('Error: ' + JSON.stringify(result.error));
                } else {
                    console.log('Unknown problem, state: ' + result.state + ', error: ' + JSON.stringify(result.error));
                }
            }));       
            helper.showHideModal(component);
        }
    })
    

    当remoteRecordId改变时,getRecord函数将会触发。它将remoteRecordId的新值动态地分配给<force:recordData>的editRecord实例,这会触发请求字段的检索。

    toggleDialog函数正在调用位于Helper文件中的函数。 Helper文件只是一个JavaScript文件,我们在其中编写我们想要重用的函数。注意saveRecord函数的末尾还有一个对showHideModal函数的调用。在标记<aura:handler name =“change”value =“{!v.showDialog}”action =“{!c.toggleDialog}”/>时,会监视showDialog属性的更改,并在发生此功能时触发。

    saveRecord函数负责保存对该属性的任何更改。它首先将三个<lightning:input>实例中的字符串值用数值转换为整数。然后它更新<force:recordData>实例的targetRecord中的值。然后使用<force:recordData>的saveRecord方法将更改保存回Salesforce。如果保存更改成功,则会触发一个名为recordUpdated的事件,我们将在下一步创建。但首先,我们将showHideModal函数添加到Helper。

  4. 单击HELPER将帮助器文件添加到组件。将占位符代码替换为:
    ({
        showHideModal : function(component) {
            var modal = component.find("editDialog");
            $A.util.toggleClass(modal, 'slds-fade-in-open');
            var overlay = component.find("overlay");
            $A.util.toggleClass(overlay, 'slds-backdrop_open');
            component.set("v.showDialog", "false");
        }
    })
    
    这个简单的函数在SLDS中打开和关闭一个CSS类来显示和/或隐藏模式。
  5. 切换回SimilarProperties组件markup.
  6. 在关闭</ lightning:card>标记之前添加一个新行(可能是第23行):
    <c:SimilarPropertyEdit showDialog="{!v.showDialog}" remoteRecordId="{!v.remoteRecordId}" />
    
    注意我们将使用remoteRecordId属性动态地将recordId分配给组件的<force:recordData>实例。
  7. 切换到SimilarProperty组件的控制器。
  8. 将editRecord函数更新为:
        editRecord : function(component, event, helper) {
        var recId = component.get("v.propertyId");
        component.set("v.remoteRecordId", recId);
        component.set("v.showDialog", "true");
    }
    

    editRecord函数现在简单地将当前记录的Id分配给RemoteRecordId属性,SimilarPropertyEdit组件用来获取其数据。 showDialog属性设置为true,这将导致SimilarPropertyEdit组件中的toggleDialog函数触发,打开自定义窗体。

    最后,我们需要添加一个Lightning事件让页面上的其他组件知道我们已经更新了记录。

  9. 在开发者控制台中,点击 File > New > Lightning Event.
  10. 命名事件 recordUpdated.

    闪电事件触发任何其他组件可以侦听的事件。事实上,我们现在要让这个组件监听这个事件,这样我们可以在页面上有多个组件实例一起更新。

  11. 切换回 SimilarProperties 组件。
  12. 在最后一个<aura:attribute>之后添加一个新行并添加:
    <aura:handler event="c:recordUpdated" action="{!c.doInit}" />
    
    现在,当组件听到recordUpdated事件时,它将触发它的doInit函数。
  13. 保存所有文件,File > Save All.
  14. 重新加载属性页面,然后单击编辑图标查看新的自定义编辑表单。

Screenshot of new edit form with Property Name, Beds, Baths, Price, and Status fields.

第7部分 – 应用微调

你做了一个了不起的工作!但是作为一个用户,当组件第一次加载到页面上时,这是一点点震动。你最初看到的只是卡片的标题栏,然后内容进来。想象一下,如果有网络问题。用户甚至可能不知道他们应该有内容,和/或最新的内容是否已经加载。 Salesforce使用微调器来指示网络活动何时发生。让我们添加一个微调器来指示何时正在检索或刷新数据。

  1. 在Developer Console中,打开主SimilarProperties组件。
  2. 在标记(可能行25)底部的<c:SimilarPropertyEdit …组件上方添加一个新行,并将以下内容添加到新行中:
    <lightning:spinner aura:id="spinner" variant="brand" size="large"/>
    
  3. 保存永远不会结束微调的文件。Screenshot of never ending spinner.

    如果刷新“财产记录”页面,则会发现一些问题。首先,微调整个页面,其次,它永远不会消失!默认情况下,<lightning:spinner>对象覆盖整个页面。但是,我们可以将其限制为只包含SLDS中的类所在的组件。

  4. 将class =“slds-is-relative”添加到<lightning:card>标记,使其看起来像这样:
    <lightning:card iconName="custom:custom85" title="Similar Properties" class="slds-is-relative">
    
  5. 保存文件。
  6. 单击STYLE将自定义CSS文件添加到SimilarProperties组件,并用下列内容替换默认内容:
    .THIS {
        min-height: 153px;
    }
    
    在Lightning组件中使用自定义CSS时,类.THIS将自动应用于包装组件的HTML元素。在这种情况下,这就是<lightning:card>。 min-height属性指定组件的最小高度。我们已经把它设置到一个财产记录的高度。
  7. 保存文件。
  8. 重新载入属性记录页面。

    您可以看到,微调控制器现在只覆盖组件,而作为加载到页面上的组件,在有数据之前,组件比之前更高。现在,我们只在数据加载时显示微调器。

  9. 在开发者控制台中,点击CONTROLLER打开SimilarPropertiesController。
  10. 将控制器代码更新为:
    ({
        doInit : function(component, event, helper) {
            var spinner = component.find("spinner");
            $A.util.removeClass(spinner, "slds-hide");
            var action = component.get("c.getSimilarProperties");
            action.setParams({
                recordId: component.get("v.recordId"),
                beds: component.get("v.property.fields.Beds__c.value"),
                price: component.get("v.property.fields.Price__c.value")
            });
            action.setCallback(this, function(response){
                var similarProperties = response.getReturnValue();
                component.set("v.similarProperties", similarProperties);
                $A.util.addClass(spinner, "slds-hide");
            });
            $A.enqueueAction(action);
        }
    })
    
    您刚刚添加了三行代码到控制器。第一行var spinner = component.find(“spinner”);为微调器创建一个变量引用。 component.find()方法用于查找标记中的元素。当我们创建<lightning:spinner>时,我们为其指定了一个“spinner”的aura:id。所以,我们说,进入标记,找到有光环的东西:微调的身份证。

    $ A.util.removeClass(s​​pinner,“slds-hide”);指示框架(记住$ A?)使用其实用方法removeClass()从微调框中删除slds-hide的CSS类。顾名思义,slds-hide类隐藏了它所放置的任何元素。因此,在slds-hide类被删除的情况下,在组件加载时,微调器将始终可见。在动作的回调中,我们添加了$ A.util.addClass(s​​pinner,“slds-hide”);它只是把slds-hide类加回到微调器上。

  11. 保存文件,然后刷新“属性记录”页面。

    现在,当我们加载数据时,微调器会短暂出现,一旦数据到达,就会消失。

第8部分 – 添加一个图标

当您创建Lightning组件时,您可以选择在Lightning App Builder中为该组件的名称旁边显示的组件创建一个图标。默认情况下,每个自定义组件都会得到一个带有白色闪电的蓝色方形图标。让我们给我们的组件自己的图标。

  1. 在开发者控制台中,点击SVG
  2. 在新的浏览器选项卡中,导航回SLDS站点。
  3. 导航到该网站的图标部分。
  4. 向下滚动以在图标的“自定义”部分中找到custom85。步骤5-13是信息性的只是因为在步骤14我们给你的图标的代码。但是,如果您想使用不同的图标,则需要执行以下步骤。
  5. 通常情况下,您可以单击导航面板中的“下载”链接,然后向下滚动到“图标”部分,然后单击“下载”按钮。
  6. 导航到下载的zip文件并解压后,打开文件夹,然后打开自定义文件夹。
  7. 找到custom85.svg文件并在文本编辑器中打开它。
  8. 复制SVG中的<path>标记。
  9. 在开发者控制台中,切换到SimilarProperties.svg。
  10. 将第二个<path>标签替换为您刚刚复制的标签。
  11. 在刚刚粘贴的<path>开始处,在“d”属性之前添加fill =“#fff”。
  12. 将<svg>标签中的width =“120px”height =“120px”viewBox =“0 0 120 120”更改为:
    width="100px" height="100px" viewBox="0 0 100 100"
    
  13. 将第一个<path>的填充更改为#F26891。
    这是我们承诺的代码!
  14. 选择全部,并使用以下命令替换Dev Console中的.svg文件:
    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <svg width="100px" height="100px" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
        <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
            <path d="M120,108 C120,114.6 114.6,120 108,120 L12,120 C5.4,120 0,114.6 0,108 L0,12 C0,5.4 5.4,0 12,0 L108,0 C114.6,0 120,5.4 120,12 L120,108 L120,108 Z" id="Shape" fill="#2A739E"/>
            <path fill="#FFF" d="m78 24h-50v-2c0-1.1-0.9-2-2-2h-4c-1.1 0-2 0.9-2 2v56c0 1.1 0.9 2 2 2h4c1.1 0 2-0.9 2-2v-46h50c1.1 0 2-0.9 2-2v-4c0-1.1-0.9-2-2-2z m-4 14h-34c-3.3 0-6 2.7-6 6v22c0 3.3 2.7 6 6 6h34c3.3 0 6-2.7 6-6v-22c0-3.3-2.7-6-6-6z m-5.5 17h-2.5v10c0 0.6-0.4 1-1 1h-4c-0.6 0-1-0.4-1-1v-6c0-0.6-0.4-1-1-1h-4c-0.6 0-1 0.4-1 1v6c0 0.6-0.4 1-1 1h-4c-0.6 0-1-0.4-1-1v-10h-2.5c-0.5 0-0.7-0.6-0.3-0.9l11.2-10.9c0.4-0.3 0.9-0.3 1.3 0l11.2 10.9c0.3 0.3 0.1 0.9-0.4 0.9z"></path>
        </g>
    </svg>
    
  15. 保存文件。
  16. 返回到“属性记录”页面,单击“设置”图标Setup icon,然后选择Edit Page.

    向下滚动到App Builder左侧栏中的自定义组件,欣赏你美丽的图标!

Screenshot of custom icon for the SimilarProperties component.

第9部分 – 添加设计参数

最后,我们将通过暴露在将组件添加到页面时可以更改的参数来使Admins爱我们。我们将给他们指定一个搜索条件的选项,以及按价格搜索的范围。我们也将确保你不会无意中将组件添加到不起作用的页面。例如,我们不想将“类似属性”组件添加到“联系人记录”页面。使用Design文件,我们可以指定组件可以使用的对象类型。因此,例如,在“联系人记录”页面上,组件将不会显示在Lightning App Builder的可用组件列表中。

  1. 如果关闭了App Builder,请在“属性记录详细信息”页面上单击“设置”图标Setup icon,然后选择Edit Page.
  2. 移除SimilarProperties组件并保存页面(注意:如果跳过这一步,在将来的步骤中编辑设计文件时会出现错误)。

    为了限制组件可以放置的页面的类型,您必须首先从分配给它的任何布局中移除该组件。

  3. 切换回开发者控制台,在SimilarProperties组件中,在最后一个<aura:attribute>之后添加一行,然后粘贴以下代码:
    <aura:attribute name="searchCriteria" type="String" default="Price" />
    <aura:attribute name="priceRange" type="String" default="100000" />
    
    为了在App Builder中公开参数,我们首先需要在组件本身中添加我们想要公开的<aura:attribute>。
  4. 将<lightning:card>的title属性更改为title =“{!’”+ v.searchCriteria}“的相似属性。它现在应该是这样的:
    <lightning:card iconName="custom:custom85" title="{! 'Similar Properties by ' + v.searchCriteria}" class="slds-is-relative">
    
  5. 保存文件。
  6. 单击CONTROLLER,然后将调用修改为action.setParams(),如下所示,以传递searchCriteria和priceRange属性的值:
    action.setParams({
            recordId: component.get("v.recordId"),
            beds: component.get("v.property.fields.Beds__c.value"),
            price: component.get("v.property.fields.Price__c.value"),
            searchCriteria: component.get("v.searchCriteria"),
            priceRange: parseInt(component.get("v.priceRange"), 10)
        });
    
  7. 保存文件。
  8. 单击设计,用下面的代码替换默认的内容:
    <design:component label="Similar Properties">
        <sfdc:objects>
            <sfdc:object>Property__c</sfdc:object>
        </sfdc:objects>
        <design:attribute name="searchCriteria" label="Search By" datasource="Bedrooms, Price" default="Price" description="Search for similar houses based on what criteria?" />
        <design:attribute name="priceRange" label="Price Range" default="100000" description="When searching by Price, search using the price plus or minus this amount" />   
    </design:component>
    

    设计属性是在App Builder中公开的参数。对于每个设计属性,在组件中必须有与设计属性完全相同名称的对应aura属性。您要公开的设计参数可以是文本输入或选择列表。应该是选择列表的参数包括一个带逗号分隔的选项列表的数据源属性,您可以在<design:attribute name =“searchCriteria”>中看到。我们还为priceRange添加了一个属性。 Apex类将使用此值来搜索加或减这个值的属性。

    <sfdc:objects>列表定义了组件可以在其上使用的对象页面的类型。如果你想在Property__c页面以外的地方使用这个组件,你只需要在列表中添加一个新的<sfdc:object>。

  9. 保存文件。 (注意:如果出现错误,请在App Builder中删除页面上的类似属性组件,然后保存。)
  10. 如果关闭了App Builder,请在“属性记录详细信息”页面上单击“设置”图标Setup icon,然后选择“编辑页面”。
  11. 单击组件列表顶部的刷新图标。

    这将重新加载组件,以便我们获得所做的更改,例如添加设计文件。
    Refresh components, insert Similar Properties Component, modify search criteria.

  12. 在“自定义组件”下,请注意组件的名称现在是“类似属性”(带有空格)。这是设计文件的标签。
  13. 将组件拖回右侧列。请注意,右侧栏目包含搜索条件的设计参数。
  14. 选择价格作为搜索条件,以75000作为价格范围。点击价格范围字段外部,让App Builder知道您已完成编辑字段。

    注意,在您进行更改时,App Builder正在刷新页面上的组件。

  15. 将组件的第二个副本拖放到页面上,并将其放在页面上第一个组件的上方或下方。
  16. 将搜索标准切换到 Bedrooms.
  17. 单击保存,然后返回到“属性记录”页面。
  18. 玩编辑卧室的价格或数量,并注意如何改变反映在组件的两个实例。

    祝贺您成为一名真正的Lightning组件开发人员。我可以说,你创造了一个惊人的组件!