Visualforce-邮件模板(4)控制器

Visualforce电子邮件模板可以利用自定义控制器呈现高度自定义的内容为此,请在使用该自定义控制器的Visualforce电子邮件模板中包含自定义组件。
例如,假设您想在电子邮件模板中显示以单词“Smith”开头的所有客户的列表。为此,首先编写一个使用SOSL调用的自定义控制器,以返回以“Smith”开头的客户列表:

public class findSmithAccounts {
private final List<Account> accounts;
public findSmithAccounts() {
accounts = [select Name from Account where Name LIKE ‘Smith_%’];
}
public List<Account> getSmithAccounts() {
return accounts;
}
}

接下来,创建一个名为smithAccounts的自定义组件,该组件使用此控制器:

<apex:component controller=”findSmithAccounts” access=”global”>
<apex:dataTable value=”{!SmithAccounts}” var=”s_account”>
<apex:column>
<apex:facet name=”header”>Account Name</apex:facet>
{!s_account.Name}
</apex:column>
</apex:dataTable>
</apex:component>

提示:请记住,Visualforce电子邮件模板中使用的所有自定义组件必须具有全局访问级别。
最后,创建一个包含smithAccounts组件的Visualforce电子邮件模板:

<messaging:emailTemplate subject=”Embedding Apex Code” recipientType=”Contact”
relatedToType=”Opportunity”>
<messaging:htmlEmailBody>
<p>As you requested, here’s a list of all our Smith accounts:</p>
<c:smithAccounts/>
<p>Hope this helps with the {!relatedToType}.</p>
</messaging:htmlEmailBody>
</messaging:emailTemplate>

请注意,尽管emailTemplate组件需要relatedToType属性,但它对此示例没有任何影响。它具有“机会”的价值只是为了表明它可以采用与自定义组件中使用的对象不同的对象值。

注意:

如果您的电子邮件模板使用标准控制器,则强制共享设置。如果用户对象的组织范围默认设置为“私人”,并且您需要访问Visualforce电子邮件模板中的用户信息(如姓名和电子邮件地址),则可以使用带有不共享关键字的自定义组件或自定义控制器。
有关共享用户对象的信息,请参阅Salesforce联机帮助中的用户共享概述。

Visualforce-邮件模板(3)附件

您可以将附件添加到Visualforce电子邮件模板。每个附件必须封装在一个<messaging:attachment>组件中。 <messaging:attachment>中的代码可以是HTML和Visualforce标签的组合。
前面的示例显示了如何通过遍历一些数据并将其显示给电子邮件收件人来创建Visualforce电子邮件模板。此示例显示如何修改该标记以将数据显示为附件:

<messaging:emailTemplate recipientType=”Contact”
relatedToType=”Account”
subject=”Case report for Account: {!relatedTo.name}”
replyTo=”support@acme.com”>
<messaging:htmlEmailBody>
<html>
<body>
<p>Dear {!recipient.name},</p>
<p>Attached is a list of cases related to {!relatedTo.name}.</p>
<center>
<apex:outputLink value=”http://www.salesforce.com”>
For more detailed information login to Salesforce.com
</apex:outputLink>
</center>
</body>
</html>
</messaging:htmlEmailBody>
<messaging:attachment>
<apex:repeat var=”cx” value=”{!relatedTo.Cases}”>
Case Number: {!cx.CaseNumber}
Origin: {!cx.Origin}
Creator Email: {!cx.Contact.email}
Case Number: {!cx.Status}
</apex:repeat>
</messaging:attachment>
</messaging:emailTemplate>

这个标记在电子邮件中作为附加的数据文件呈现,没有任何格式。您可以使用以下选项之一以更易读的格式显示数据:

更改文件名

<messaging:attachment>标记具有一个名为filename的属性,用于定义附加文件的名称。定义一个容易识别的名字是一个好习惯,但这不是必需的。如果不确定,Salesforce会为您生成一个名称。
没有扩展名的文件名默认为文本文件。您可以将附件呈现为CSV格式:

<messaging:attachment filename=”cases.csv”>
<apex:repeat var=”cx” value=”{!relatedTo.Cases}”>
{!cx.CaseNumber}
{!cx.Origin}
{!cx.Contact.email}
{!cx.Status}
</apex:repeat>
</messaging:attachment>

您也可以将数据呈现为HTML文件:

<messaging:attachment filename=”cases.html”>
<html>
<body>
<table border=”0″ >
<tr>
<th>Case Number</th><th>Origin</th>
<th>Creator Email</th><th>Status</th>
</tr>
<apex:repeat var=”cx” value=”{!relatedTo.Cases}”>
<tr>
<td><a href =
“https://na1.salesforce.com/{!cx.id}”>{!cx.CaseNumber}
</a></td>
<td>{!cx.Origin}</td>
<td>{!cx.Contact.email}</td>
<td>{!cx.Status}</td>
</tr>
</apex:repeat>
</table>
</body>
</html>
</messaging:attachment>

尽管您只能为每个<messaging:attachment>组件定义一个文件名,但可以将多个文件附加到电子邮件中。

更改呈现属性

与其他Visualforce页面类似,在<messaging:attachment>组件上将renderAs属性设置为PDF将使该附件呈现为PDF。例如:

<messaging:attachment renderAs=”PDF” filename=”cases.pdf”>
<html>
<body>
<p>You can display your {!relatedTo.name} cases as a PDF:</p>
<table border=”0″ >
<tr>
<th>Case Number</th><th>Origin</th>
<th>Creator Email</th><th>Status</th>
</tr>
<apex:repeat var=”cx” value=”{!relatedTo.Cases}”>
<tr>
<td><a href =
“https://na1.salesforce.com/{!cx.id}”>{!cx.CaseNumber}
</a></td>
<td>{!cx.Origin}</td>
<td>{!cx.Contact.email}</td>
<td>{!cx.Status}</td>
</tr>
</apex:repeat>
</table>
</body>
</html>
</messaging:attachment>

Visualforce PDF呈现服务的限制包括以下内容。

  • PDF是唯一支持的呈现服务。
  • PDF呈现服务呈现PDF版本1.4。
  • 将Visualforce页面呈现为PDF文件适用于为打印设计和优化的页面。
  • 作为PDF文件呈现的Visualforce页面显示在浏览器中,或根据浏览器的设置进行下载。具体行为取决于浏览器,版本和用户设置,并且不受Visualforce的控制。
  • PDF呈现服务在您的页面上呈现标记和数据,但是它可能不会呈现包含在添加到页面的富文本区域内容中的格式。
  • 没有断点的长行文本(如空格或破折号)不能由PDF呈现服务打包。这通常发生在非常长的URL,注册表项等等。当这些行比页面宽时,它们会增加页面内容的宽度,超出PDF页面的边缘。这会导致内容从页面“流”,切断它。
  • 不要使用不易打印格式的标准组件,或输入或按钮等表单元素,或任何需要JavaScript格式的组件。
  • PDF渲染不支持JavaScript呈现的内容。
  • Salesforce应用程序中的页面不支持PDF呈现。
  • 页面上使用的字体必须在Visualforce PDF呈现服务上可用。 Web字体不受支持。
  • 如果PDF文件无法显示所有页面的文本,特别是多字节字符(如日文或重音国际字符),请调整CSS以使用支持它们的字体。 例如:
    <apex:page showHeader=”false” applyBodyTag=”false” renderAs=”pdf”>
    <head>
    <style>
    body { font-family: ‘Arial Unicode MS’; }
    </style>
    </head>
    <body>
    これはサンプルページです。<br/>
    This is a sample page: API version 28.0
    </body>
    </apex:page>
    “Arial Unicode MS”是包含多字节字符的扩展字符集所支持的唯一字体。
  • 如果使用内联CSS样式,请将API版本设置为28.0或更高版本。同样设置<apex:page applyBodyTag =“false”>,并在页面中添加静态的,有效的<head>和<body>标签,就像前面的例子。
  • 创建PDF文件时的最大响应大小必须小于15 MB,然后才能呈现为PDF文件。此限制是所有Visualforce请求的标准限制。
  • 生成的PDF文件的最大文件大小为60 MB。
  • 生成的PDF中包含的所有图像的最大总大小为30 MB。
  • PDF呈现不支持以数据:URI方案格式编码的图像。
  • 以PDF形式呈现时,以下组件不支持双字节字体。
    – <apex:pageBlock>
    – <apex:sectionHeader>
    不推荐将这些组件用于以PDF形式呈现的页面。
  • 如果<apex:dataTable>或<apex:pageBlockTable>没有呈现<apex:column>组件,则将该页呈现为PDF失败。 要解决此问题,请将表组件的呈现属性设置为false,如果未呈现其任何子<apex:column>组件。

添加样式和图像

附件还可以使用样式表来改变数据的呈现方式。 样式以与在Visualforce电子邮件模板中的方式相同的方式与内嵌代码或通过使用自定义组件相关联。
呈现为PDF的附件可以通过$ Resource全局变量引用静态资源。 这使您可以引用PDF正文中的图像或样式表。
例如,以下附件在PDF中包含徽标:

<messaging:attachment renderAs=”PDF” filename=”cases.pdf”>
<html>
<body>
<img src = “{!$Resource.logo}” />

</body>
</html>
</messaging:attachment>

这个附件引用了一个你保存为静态资源的样式表:

<messaging:attachment renderAs=”PDF”>
<html>
<link rel=’stylesheet’ type=’text/css’ href='{!$Resource.EMAILCSS}’ />
<body>

</body>
</html>
</messaging:attachment>

警告:引用远程服务器上的静态资源可能会增加呈现PDF附件所需的时间。 在Apex触发器中创建PDF附件时,不能引用远程资源; 这样做会导致例外。

Visualforce-邮件模板(2)样式

默认情况下,Visualforce电子邮件模板始终使用其他Salesforce组件的标准外观。但是,您可以通过定义自己的样式表来扩展或覆盖这些样式。
与其他Visualforce页面不同,Visualforce电子邮件模板不能使用引用的页面样式或静态资源。尽管CSS似乎在电子邮件模板预览窗格中呈现,但它与您的电子邮件的收件人不同。您必须在<style>标签内使用CSS定义您的样式。
以下示例将电子邮件的字体更改为Courier,将边框添加到表中,并更改表格行的颜色:

<messaging:emailTemplate recipientType=”Contact”
relatedToType=”Account”
subject=”Case report for Account: {!relatedTo.name}”
replyTo=”support@acme.com”>
<messaging:htmlEmailBody>
<html>
<style type=”text/css”>
body {font-family: Courier; size: 12pt;}
table {
border-width: 5px;
border-spacing: 5px;
border-style: dashed;
border-color: #FF0000;
background-color: #FFFFFF;
}
td {
border-width: 1px;
padding: 4px;
border-style: solid;
border-color: #000000;
background-color: #FFEECC;
}
th {
color: #000000;
border-width: 1px ;
padding: 4px ;
border-style: solid ;
border-color: #000000;
background-color: #FFFFF0;
}
</style>
<body>
<p>Dear {!recipient.name},</p>
<table border=”0″ >
<tr>
<th>Case Number</th><th>Origin</th>
<th>Creator Email</th><th>Status</th>
</tr>
<apex:repeat var=”cx” value=”{!relatedTo.Cases}”>
<tr>
<td><a href =
“https://na1.salesforce.com/{!cx.id}”>{!cx.CaseNumber}
</a></td>
<td>{!cx.Origin}</td>
<td>{!cx.Contact.email}</td>
<td>{!cx.Status}</td>
</tr>
</apex:repeat>
</table>
</body>
</html>
</messaging:htmlEmailBody>
</messaging:emailTemplate>

在自定义组件中定义Visualforce样式表

虽然您无法在Visualforce电子邮件模板中引用外部样式表,但您可以将样式定义放置在可在其他位置引用的自定义组件中。例如,您可以修改前面的示例以将样式信息放入名为EmailStyle的组件中:

<apex:component access=”global”>
<style type=”text/css”>
body {font-family: Courier; size: 12pt;}
table {
border-width: 5px;
border-spacing: 5px;
border-style: dashed;
border-color: #FF0000;
background-color: #FFFFFF;
}
td {
border-width: 1px;
padding: 4px;
border-style: solid;
border-color: #000000;
background-color: #FFEECC;
}
th {
color: #000000;
border-width: 1px ;
padding: 4px ;
border-style: solid ;
border-color: #000000;
background-color: #FFFFF0;
}
</style>
</apex:component>

然后,在Visualforce电子邮件模板中,您只能引用该组件:

<messaging:htmlEmailBody>
<html>
<c:EmailStyle />
<body>
<p>Dear {!recipient.name},</p>

</body>
</html>
</messaging:htmlEmailBody>

注意:在Visualforce电子邮件模板中使用的任何<apex:component>标记都必须具有全局访问级别。

Visualforce-邮件模板(1)创建

开发人员和管理员可以使用Visualforce创建电子邮件模板。使用Visualforce超过标准HTML的优势电子邮件模板是Visualforce使您能够对发送给收件人的数据执行高级操作。
虽然Visualforce电子邮件模板使用标准的Visualforce组件,但它们不是以相同的方式创建的。 Visualforce电子邮件模板始终使用以消息传递名称空间开头的组件。此外:

  • 所有Visualforce电子邮件模板必须包含在一个<messaging:emailTemplate>标记中。这与在单个<apex:page>标签中定义的常规Visualforce页面类似。
  • <messaging:emailTemplate>标记必须包含单个<messaging:htmlEmailBody>标记或单个<messaging:plainTextEmailBody>标记。
  • 几个标准的Visualforce组件在<messaging:emailTemplate>中不可用。这些包括<apex:detail>,<apex:pageBlock>和所有相关的pageBlock组件以及所有输入组件,如<apex:form>。如果您尝试使用这些组件保存Visualforce电子邮件模板,则会显示一条错误消息。

创建一个Visualforce电子邮件模板

  1. 执行以下操作之一:
    • 如果您有权编辑公共模板,请从“设置”中,在快速查找方框中输入电子邮件模板,然后选择电子邮件模板。
    • 如果您无权修改公共模板,请转到个人设置。在快速查找框中输入模板,然后选择电子邮件模板或我的模板 – 无论哪一个出现。
  2. 点击 New Template.
  3. 选择 Visualforce 然后单击 Next.
    您无法使用Visualforce电子邮件模板发送群发电子邮件。
  4. 选择一个文件夹来存储模板。
  5. 要使模板可供使用,请选择可用的复选框。
  6. 在电子邮件模板名称中输入名称。
  7. 如有必要,请更改模板唯一名称。这个唯一的名称是指使用Force.com API时的组件。在托管包中,此唯一名称可防止程序包安装中的命名冲突。此名称只能包含下划线和字母数字字符,并且在您的组织中必须是唯一的。它必须以字母开头,不能包含空格,不能以下划线结尾,并且不要包含两个连续的下划线。使用“模板唯一名称”字段,可以更改托管数据包中某些组件的名称,这些更改将反映在订户组织中。
  8. 如果需要,请从编码下拉列表中选择不同的字符集。
  9. 输入模板的描述。模板名称和说明仅供您内部使用。
  10. 在电子邮件主题中输入您的模板的主题行。
  11. 在“收件人类型”下拉列表中,选择要从模板创建的收件人的类型。
  12. 如果需要,请在相关类型下拉列表中选择模板检索合并字段数据的对象。
  13. 点击 Save.
  14. 在Salesforce Classic页面的查看电子邮件模板中,单击编辑模板。
  15. 为您的Visualforce电子邮件模板输入标记文本。
    注意:如果您正在添加图片,我们建议将其上传到“文档”选项卡,以引用服务器上的图像副本。例如:
    <apex:image id=”Logo”
    value=”https://yourInstance.salesforce.com/servlet/servlet.ImageServer?
    id=015D0000000Dpwc&oid=00DD0000000FHaG&lastMod=127057656800″ />
  16. 要指定Visualforce的版本以及此电子邮件模板使用的API,请单击版本设置。如果您已经通过AppExchange安装了托管软件包,则还可以指定每个托管软件包的哪个版本与此电子邮件模板配合使用。通常,使用所有版本的默认值,将电子邮件模板与最新版本的Visualforce,API和每个托管软件包相关联。要保持特定的行为,您可以指定较旧版本的Visualforce和API。要访问与最新软件包版本不同的组件或功能,可以指定旧版本的托管软件包。
  17. 要查看模板的详细信息,请单击保存。要继续编辑您的模板,请点击快速保存。在保存模板之前,您的Visualforce标记必须有效。

注意:

Visualforce电子邮件模板的最大大小为1 MB。
您无法使用Visualforce电子邮件模板发送群发电子邮件。 {!Receiving_User.field_name}和
{!Sending_User.field_name}合并字段仅适用于海量电子邮件和列表电子邮件,并且在Visualforce电子邮件模板中不可用。

以下示例显示如何定义显示与联系人关联的所有情况的Visualforce电子邮件模板。 该示例使用<apex:repeat>标签遍历与联系人有关的所有情况,并将它们合并到主体中
模板:

<messaging:emailTemplate recipientType=”Contact”
relatedToType=”Account”
subject=”Case report for Account: {!relatedTo.name}”
language=”{!recipient.Languages__c}”
replyTo=”support@acme.com”>
<messaging:htmlEmailBody>
<html>
<body>
<p>Dear {!recipient.name},</p>
<p>Below is a list of cases related to {!relatedTo.name}.</p>
<table border=”0″ >
<tr>
<th>Case Number</th><th>Origin</th>
<th>Creator Email</th><th>Status</th>
</tr>
<apex:repeat var=”cx” value=”{!relatedTo.Cases}”>
<tr>
<td><a href =
“https://yourInstance.salesforce.com/{!cx.id}”>{!cx.CaseNumber}
</a></td>
<td>{!cx.Origin}</td>
<td>{!cx.Contact.email}</td>
<td>{!cx.Status}</td>
</tr>
</apex:repeat>
</table>
<p/>
<center>
<apex:outputLink value=”http://www.salesforce.com”>
For more detailed information login to Salesforce.com
</apex:outputLink>
</center>
</body>
</html>
</messaging:htmlEmailBody>
</messaging:emailTemplate>

注意以下关于标记:

  • recipientType和relatedToType属性充当电子邮件模板的控制器。有了它们,您可以访问其他标准控制器可用的相同合并字段。 recipientType属性表示电子邮件的收件人。 relatedToType属性表示与电子邮件关联的记录。 
  • <messaging:htmlEmailBody>组件可以包含Visualforce标记和HTML的组合。 <messaging:plainTextEmailBody>组件只能包含Visualforce标记和纯文本。 
  • 要根据收件人或相关对象的语言翻译Visualforce电子邮件模板,请使用
    <messaging:emailTemplate>标签的语言属性(有效值:Salesforce支持的语言键,例如“en-US”)。 language属性接受来自电子邮件模板的recipientType和relatedToType属性的合并字段。您可以创建用于合并字段的自定义语言字段。翻译工作台需要翻译电子邮件模板。该示例使用合并字段为接收电子邮件的联系人获取语言属性。

Salesforce Visualforce (基础9)自定义控制器

学习目标

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

  • 解释一下自定义控制器是什么,并描述其关键属性。
  • 创建一个自定义控制器类。
  • 在Visualforce页面上使用自定义控制器。

自定义控制器介绍

自定义控制器包含可由Visualforce页面使用的自定义逻辑和数据操作。例如,自定义控制器可以检索要显示的项目列表,向外部Web服务发出调用,验证和插入数据等等,并且所有这些操作都将可用于Visualforce页面,该页面将其用作控制器。
在其他地方介绍了Visualforce如何支持用于构建Web应用程序的模型 – 视图 – 控制器(MVC)设计模式。控制器通常检索要在Visualforce页面中显示的数据,并包含响应页面操作而执行的代码(如正在单击的按钮)。当您使用标准控制器时,平台为您提供了大量的标准功能。

但是一个尺寸并不适合所有的,并不是所有的网络应用程序都是“标准的”。当你想覆盖现有的功能,通过应用程序自定义导航,使用标注或Web服务,或者如果你需要更好地控制信息的访问方式对于您的页面,Visualforce可让您占据统治地位。您可以使用Apex编写自定义控制器,并从头到尾完全控制您的应用逻辑。

创建一个使用自定义控制器的Visualforce页面

通过在<apex:page>控制器属性中引用控制器类的名称,将自定义控制器添加到Visualforce页面。
当您的页面使用自定义控制器时,不能使用标准控制器。页面使用不同的属性来设置自定义控制器。
  1. 打开开发者控制台,然后点击 File | New | Visualforce Page 创建一个新的Visualforce页面。输入ContactsListController作为页面名称。
  2. 在编辑器中,用以下替换标记。
    <apex:page controller="ContactsListController">
        <apex:form>
            <apex:pageBlock title="Contacts List" id="contacts_list">
                
                <!-- Contacts List goes here -->
    
            </apex:pageBlock>
        </apex:form>
    </apex:page>
    当你试图保存这个页面时,你会得到一个错误,因为ContactsListController还不存在。不用担心,接下来我们会解决这个问题。

创建一个自定义控制器Apex类

自定义控制器只是一个Apex类,您可以使用Developer Console编写自己的类。
有许多系统和实用程序类可以帮助您编写自定义控制器逻辑,但将类用作自定义控制器的唯一要求是它存在。
  1. 打开开发者控制台,然后点击 File | New | Apex Class 创建一个新的Apex类。输入ContactsListController作为类名。
  2. 在编辑器中,用以下代码替换任何代码。
    public class ContactsListController {
    
        // Controller code goes here
    
    }
    与Visualforce页面一样,当您更改时,您需要保存对Apex的更改。
    这并不多,而且还没有做任何事情,但它确实使错误消失在Visualforce页面上。所以…
  3. 切换回Visualforce页面并再次保存。
    错误信息应该消失,页面成功保存。
  4. 点击预览打开您的页面的预览,您可以在进行更改时查看。
    应该打开一个新窗口,显示标准的Salesforce页面标题和侧边栏元素,但没有内容。

乍一看,你创建的这两个新项目看起来并不是很有趣。但是即使它们是90%的占位符代码,Visualforce页面和Apex控制器这两个项目也是相互关联的。只要你添加更多的代码到控制器,你的页面就可以使用它。

超越基础

您可能已经注意到,这个自定义控制器类不会从另一个类继承,也不会实现一个有希望符合Visualforce控制器要求的接口。即使是复杂的控制器也不会做这些事情,因为没有任何这样的类继承或接口实现。这使您可以自由地创建自己的类和接口,随着您对Apex的经验的增加。

添加一个方法来检索记录

创建一个运行SOQL查询的getter方法,该查询返回要在页面上显示的记录。
大多数控制器的主要目的是检索显示数据或处理数据更新。在这个简单的控制器中,您只需运行一个基本的SOQL查询来查找联系人记录,然后使这些记录可用于Visualforce页面。
  1. 在ContactsListController类中,用下面的代码替换// Controller代码在这里注释行。
    private String sortOrder = 'LastName';
        
    public List<Contact> getContacts() {
        
        List<Contact> results = Database.query(
            'SELECT Id, FirstName, LastName, Title, Email ' +
            'FROM Contact ' +
            'ORDER BY ' + sortOrder + ' ASC ' +
            'LIMIT 10'
        );
        return results;
    }
    此代码添加一个私有成员变量,一个名为sortOrder的字符串和一个公共方法getContacts()。 sortOrder很容易理解,它只是通过排序联系人的字段的名称。
    getContacts()也是相当简单的,但是如果你以前没有见过Apex,可能起初很难解析。该方法的作用是执行SOQL查询以获取联系人记录列表,然后将该联系人列表返回给方法调用者。来电者是谁?当然是Visualforce页面!
  2. 在ContactsListWithController页面中,将<! – 联系人列表转到这里 – >注释行替换为以下标记。
    <!-- Contacts List -->
    <apex:pageBlockTable value="{! contacts }" var="ct">
    
        <apex:column value="{! ct.FirstName }"/>
        <apex:column value="{! ct.LastName }"/>
        <apex:column value="{! ct.Title }"/>
        <apex:column value="{! ct.Email }"/>
        
    </apex:pageBlockTable>
    当您保存此页面时,您应该看到一张熟悉的联系信息表格。
    A contacts list backed by a custom controller

ContactsListWithController页面的标记应该看起来相当熟悉。除了<apex:page>标签的控制器属性之外,它与用标准控制器创建页面的代码大致相同。

不同的是当{!联系人}表达式进行评估。在此页面上,Visualforce将该表达式转换为对控制器的getContacts()方法的调用。该方法返回联系人记录列表,这正是<apex:pageBlockTable>所期望的。

getContacts()方法被称为getter方法,它是一个通用模式,其中{!您的Visualforce标记中的someExpression}将自动连接到控制器中名为getSomeExpression()的方法。这是让页面访问需要显示的数据的最简单的方法。

添加一个新的操作方法

在自定义控制器中创建操作方法以响应用户在页面上的输入。
显示数据很棒,但是对用户操作的回应对于任何网络应用程序都是至关重要的使用自定义控制器,您可以通过编写操作方法来响应用户活动,从而创建尽可能多的自定义操作,以支持页面。
  1. 在ContactsListController类中,getContacts()方法的下面添加以下两个方法。
    public void sortByLastName() {
        this.sortOrder = 'LastName';
    }
        
    public void sortByFirstName() {
        this.sortOrder = 'FirstName';
    }
    这两个方法改变了sortOrder私有变量的值。在检索联系人的SOQL查询中使用sortOrder,并且更改sortOrder将更改结果的顺序。
  2. 在ContactsListWithController页面中,使用以下标记替换ct.FirstName和ct.LastName的两个<apex:column>标记。
    <apex:column value="{! ct.FirstName }">
        <apex:facet name="header">
            <apex:commandLink action="{! sortByFirstName }" 
                reRender="contacts_list">First Name
            </apex:commandLink>
        </apex:facet>
    </apex:column>
    
    <apex:column value="{! ct.LastName }">
        <apex:facet name="header">
            <apex:commandLink action="{! sortByLastName }" 
                reRender="contacts_list">Last Name
            </apex:commandLink>
        </apex:facet>
    </apex:column>

    尽管可视外观保持不变,但如果现在单击“名字和姓氏”列标题,它们将更改联系人列表的排序顺序。太好了!
    新的标记将两个嵌套组件添加到每个<apex:column>组件。 <apex:column>本身有一个纯文本标题,但是我们希望使标题可点击。 <apex:facet>让我们将列标题的内容设置为我们想要的任何内容。而我们想要的是一个调用正确的操作方法的链接。该链接是使用<apex:commandLink>组件创建的,action属性设置为引用控制器中action方法的表达式。 (请注意,与getter方法相比,action方法的名称与引用它们的表达式相同。)

    点击链接时,会触发控制器中的操作方法。该操作方法更改排序顺序专用变量,然后该表被重新渲染。当表格被重新渲染时,{!联系人}被重新评估,重新查询以任何排序顺序刚刚设置。最终的结果是按照用户点击所请求的顺序来使用表格。

超越基础

名字和姓氏列的标题文本在这个标记中被硬编码。但是,如果你的用户不全都使用英文呢?标准Salesforce用户界面已翻译所有标准对象的字段名称版本,并且可以为自定义对象提供自己的翻译。你将如何访问这些?试试这个标记,而不是纯文本:<apex:outputText value =“{!$ ObjectType.Contact.Fields.FirstName.Label}”/>。即使您的组织使用相同的语言,这也是引用字段标签的正确方法,因为如果字段名称被更改,它将自动更新。

告诉我更多…

自定义控制器和Apex语言让您可以在Visualforce页面中完成任何您能想到的任何事情。
Getter方法将数据从您的控制器中拖出到您的页面上。有相应的setter方法可以让你从页面提交值到你的控制器。就像getter方法一样,你在setter前面加上“set”,除此之外,它们只是一个方法。

getter和setter的替代方法是使用Apex属性。属性是一种变量与getter和setter方法的组合,它们的语法可以更清楚地将它们组合在一起。引用自定义对象的简单属性可能会这样声明。

public MyObject__c myVariable { get; set; }

属性可以是公共的或私有的,可以是只读的,甚至可以只写,通过省略get或set。你可以为get或set方法创建实现,当你想要执行额外的逻辑,除了简单地保存和检索一个值。

属性是Apex的一般功能,不是Visualfor特有的。 Apex是一种完整的编程语言,除了成为构建复杂的Visualforce页面的天然合作伙伴外,它还被用于许多其他的Force.com开发环境。请参阅此处其他位置的Apex主题以及本页末尾的资源,了解如何学习充分利用Apex。

Visualforce请求和响应的生命周期最初可能看起来很复杂。尤其重要的是要明白,没有特定的getter或setter(或属性,如果你使用它们)的顺序被调用,所以你不能在它们之间引入顺序执行的依赖关系。 Visualforce开发人员指南的相关章节中提供了更多详细信息,特别是“自定义控制器和控制器扩展”一章。