在本文中,我们将通过一个示例说明如何将“流”(Visual Flow)用于Visualforce页面。
更全面的知识可以参考官方文档。
创建流
我们要创建一个流,它的作用是得到一个“客户”(Account)变量,然后根据其中的自定义字段“是否破产”(Bankrupt__c)来决定是否在客户名称后面加上“已破产”的字样。
步骤如下:
- 在新的流中创建一个“SObject对象变量”,这个变量会用于存储“客户”对象的信息
- 创建一个“决策”元素,在其中检查刚才建立的客户变量的“是否破产”字段值
- 创建一个“分配”元素,和上一步“决策”变量中“已破产”的结果相连接,在其中将客户变量的名称字段后面加上“已破产”字样
- 创建一个“快速更新”元素,更新客户变量
完成后的流程图如下:
保存为“流”类型,设置名称为“Check_and_update_bankrupt”,并启用该流。
这时,我们还不能使用它,因为这个流在使用前需要先得到一个“客户”对象。要实现这一点,就需要使用一个Visualforce页面来加载“客户”对象并调用流。
创建Visualforce页面
要将创建的“流”使用于Visualforce页面中,可以使用以下步骤:
在“设置”界面搜索“Visualforce 页面”,点击“Visualforce 页面”链接,进入Visualforce页面的一览表
点击“新建”按钮,新建Visualforce页面
设置“标签”和“名称”属性。设置名称为“Check_Bankrupt_And_Update_Name”
在“Visualforce Markup”部分删除原有的代码,改为:
<apex:page StandardController="Account">
<flow:interview name="Check_and_update_bankrupt"></flow:interview>
</apex:page>
这里使用了“flow:interview”组件调用了刚才建立的“流”,并且将页面的“StandardController”属性设置为“Account”,标明该页面和“客户”对象相联系
保存此Visualforce页面
建立按钮调用Visualforce页面
在“客户”的“按钮、链接和操作”部分,新建一个按钮,并将“内容源”设置为“Visualforce页面”。
系统会自动检测所有的Visualforce页面,并在下拉列表中显示“StandardController”属性为“Account”的页面。
在下拉列表中选择刚才建立的页面,保存。
然后将此按钮添加到“客户”的页面布局。
这样,用户在客户的详细信息页面点击“检查破产并更新名称”按钮,就可以使用流了。
将参数传入流
现在还差最后一步工作,就是将按钮所在的客户页面的客户变量传入流中,让流知道哪个“客户”对象需要被检查和更新。
编辑刚才建立的Visualforce页面,在“flow:interview”组件中进行如下修改:
<apex:page StandardController="Account">
<flow:interview name="Check_and_update_bankrupt">
<apex:param name="AccountVar" value="{!account}"/>
</flow:interview>
</apex:page>
从上面的代码中可以看到,我们使用了“apex:param”标签来设置流中使用的变量“AccountVar”。
但是这时,如果在客户页面中点击刚才建立的按钮,会直接出现错误。当我们检查调试日志时,会发现这样的错误信息:“流无法访问AccountVar.Bankrupt__c的值”。
这是因为我们在Visualforce页面中通过标准的“Account”控制器传入参数时,标准的控制器并不会调用“客户”对象下面的字段,从而无法检查“Bankrupt__c”的值。
这时,我们需要新建一个Apex类,作为标准“Account”控制器的扩展,在其中要求系统调用“Name”和“Bankrupt__c”字段的值。新建的Apex类如下:
public class AccountCheckBankruptExtension {
private final Account acc;
public AccountCheckBankruptExtension(ApexPages.StandardController stdController) {
stdController.addFields(new List<String>{'Name', 'Bankrupt__c'});
this.acc = (Account)stdController.getRecord();
}
}
然后将刚才的Visualforce页面修改为:
<apex:page StandardController="Account" Extensions="AccountCheckBankruptExtension">
<flow:interview name="Check_and_update_bankrupt">
<apex:param name="AccountVar" value="{!account}"/>
</flow:interview>
</apex:page>
这时,在“是否破产”值为“真”的客户页面点击“检查破产并更新名称”按钮,就可以运行流了。
设置返回跳转链接
虽然流可以顺利运行了,但是流的执行是在新的窗口中执行,结束后会给出“流执行完毕”的字样。为了提高用户体验,我们需要让流在运行结束后返回处理的“客户”页面,从而直接将结果展示为用户。
将刚才的Visualforce页面修改为:
<apex:page StandardController="Account" Extensions="AccountCheckBankruptExtension">
<flow:interview name="Check_and_update_bankrupt" finishLocation="{!URLFOR('/' + account.Id)}">
<apex:param name="AccountVar" value="{!account}"/>
</flow:interview>
</apex:page>
在这里,我们使用了“finishLocation”属性来设置流完成后跳转的页面,即跳转到“客户”变量详细信息页面。
执行结果
现在我们就可以检查整个过程了。
首先,进入一个客户的详细信息页面,将“是否破产”改为“真”。
然后点击“检查破产并更新名称”按钮,会弹出一个新的页面。这就是刚才建立的Visualforce页面。在其中,流将会被执行。结束后,跳转到刚才的客户页面。
可以看到,“客户”的“名称”部分已经被加入了“(已破产)”的字样。流执行成功了。
扩展知识
流的变量设定
在流中新建“SObject变量”时,需要将变量的“输入/输出类型”设置为“输入和输出”。否则,此变量有可能无法被Visualforce页面和相应的控制器调用。
在Apex代码中使用Flow.Interview类
在Apex代码中使用Flow.Interview类可以直接引用执行的流的实例,并且可以使用getVariableValue()函数来得到流中的变量的值。
比如上述的示例中,将Apex代码改为:
public class AccountCheckBankruptExtension {
public Flow.Interview.Check_and_update_bankrupt flowInstance {get; set;}
private final Account acc;
public AccountCheckBankruptExtension(ApexPages.StandardController stdController) {
stdController.addFields(new List<String>{'Name', 'Bankrupt__c'});
this.acc = (Account)stdController.getRecord();
}
public String getAccName() {
Account accInFlow = (Account) flowInstance.getVariableValue('AccountVar');
return accInFlow.Name;
}
}
在代码中增加了一个变量“flowInstance”,类型是“Flow.Interview.流的名字”。同时也增加了一个函数getAccName(),使用了getVariableValue()函数得到流中的“客户”变量的名称。
将Visualforce页面的代码改为:
<apex:page StandardController="Account" Extensions="AccountCheckBankruptExtension">
<flow:interview name="Check_and_update_bankrupt" interview="{!flowInstance}">
<apex:param name="AccountVar" value="{!account}"/>
</flow:interview>
<apex:outputtext>客户名称:{!accName}</apex:outputtext>
</apex:page>
这样,我们成功的得到了客户的名称,显示在页面底部。