有人能否澄清一下,我们如何在一般情况下或者一个真实世界的例子中使用这个代码片段?
<f:metadata>
<f:viewParam id="id" value="#{bean.id}" />
<f:viewAction action="#{bean.init}" />
</f:metadata>
有人能否澄清一下,我们如何在一般情况下或者一个真实世界的例子中使用这个代码片段?
<f:metadata>
<f:viewParam id="id" value="#{bean.id}" />
<f:viewAction action="#{bean.init}" />
</f:metadata>
<f:viewParam>
管理GET参数的设置、转换和验证。它类似于 <h:inputText>
,但是针对 GET 参数。
以下示例:
<f:metadata>
<f:viewParam name="id" value="#{bean.id}" />
</f:metadata>
基本上会执行以下操作:
id
获取请求参数值。required
、validator
和converter
属性,并像在<h:inputText>
中嵌套<f:converter>
和<f:validator>
一样处理)#{bean.id}
值表示的bean属性,或者如果不存在value
属性,则将其设置为请求属性,名称为id
,以便在视图中通过#{id}
使用。因此,当您打开页面作为foo.xhtml?id=10
时,参数值10
以这种方式设置在bean中,在视图呈现之前。
关于验证,以下示例将参数设置为required="true"
,并仅允许介于10和20之间的值。任何验证失败都将导致显示消息。
<f:metadata>
<f:viewParam id="id" name="id" value="#{bean.id}" required="true">
<f:validateLongRange minimum="10" maximum="20" />
</f:viewParam>
</f:metadata>
<h:message for="id" />
您可以使用<f:viewAction>
来实现此功能。
<f:metadata>
<f:viewParam id="id" name="id" value="#{bean.id}" required="true">
<f:validateLongRange minimum="10" maximum="20" />
</f:viewParam>
<f:viewAction action="#{bean.onload}" />
</f:metadata>
<h:message for="id" />
使用
public void onload() {
// ...
}
< p > <f:viewAction>
自 JSF 2.2 版本开始新增(<f:viewParam>
已经存在于 JSF 2.0)。如果您无法升级,则最好使用 <f:event>
。
<f:event type="preRenderView" listener="#{bean.onload}" />
然而,这将在每个请求上调用。您需要明确检查请求是否不是postback:
public void onload() {
if (!FacesContext.getCurrentInstance().isPostback()) {
// ...
}
}
如果您希望在出现“转换/验证失败”情况时也跳过,那么请按照以下步骤操作:
public void onload() {
FacesContext facesContext = FacesContext.getCurrentInstance();
if (!facesContext.isPostback() && !facesContext.isValidationFailed()) {
// ...
}
}
<f:event>
的方式本质上是一种解决方法/技巧,这就是为什么在JSF 2.2中引入了<f:viewAction>
的原因。
您可以通过将includeViewParams
属性设置为true
或添加includeViewParams=true
请求参数,在导航链接中“传递”视图参数。
<h:link outcome="next" includeViewParams="true">
<!-- Or -->
<h:link outcome="next?includeViewParams=true">
这将基本上生成与上面的<f:metadata>
示例相同的链接。
<a href="next.xhtml?id=10">
保留原始参数值。
这种方法只需要要求在next.xhtml
上也有一个相同的<f:viewParam>
,否则它不会被传递。
<f:viewParam>
也可以与"纯HTML" GET表单结合使用。
<f:metadata>
<f:viewParam id="query" name="query" value="#{bean.query}" />
<f:viewAction action="#{bean.search}" />
</f:metadata>
...
<form>
<label for="query">Query</label>
<input type="text" name="query" value="#{empty bean.query ? param.query : bean.query}" />
<input type="submit" value="Search" />
<h:message for="query" />
</form>
...
<h:dataTable value="#{bean.results}" var="result" rendered="#{not empty bean.results}">
...
</h:dataTable>
基本上有这个@RequestScoped
bean:
private String query;
private List<Result> results;
public void search() {
results = service.search(query);
}
<h:message>
是为<f:viewParam>
而不是普通的HTML <input type="text">
!还要注意,当#{bean.query}
为空时,输入值会显示#{param.query}
,因为在验证或转换错误时,否则提交的值将完全不显示。请注意,这种结构对于JSF输入组件无效(它已经在“幕后”执行了此操作)。
将参数从一个视图发送到另一个视图,从发送视图到接收视图使用viewParam和includeViewParams=true
在发送者中
Sender.xhtml
<f:metadata>
<f:viewParam name="ID" value="#{senderMB._strID}" />
</f:metadata>
Sender.xhtml
<p:dataTable rowIndexVar="index" id="dataTale"value="#{senderMB._arrData}" var="dto">
<p:commandButton action="#{senderMB.clickBtnDetail(dto)}" value="見る"
ajax="false"/>
</p:dataTable>
Sender_MB.java
public String clickBtnDetail(sender_DTO sender_dto) {
this._strID = sender_dto.getStrID();
return "Receiver?faces-redirect=true&includeViewParams=true";
}
http://localhost:8080/my_project/view/Receiver.xhtml?*ID=12345*
在Receiver中
Receiver.xhtml
<f:metadata><f:viewParam name="ID" value="#{receiver_MB._strID}"/></f:metadata>
它将从发送方视图获取参数ID并分配给接收方_MB._strID
Receiver.xhtml
<f:event listener="#{receiver_MB.preRenderView}" type="preRenderView" />
标签转换为标签。
Receiver.xhtml
<f:metadata>
<f:viewParam name="ID" value="#{receiver_MB._strID}" />
<f:event listener="#{receiver_MB.preRenderView}"
type="preRenderView" />
</f:metadata>
Receiver_MB.java
public void preRenderView(ComponentSystemEvent event) throws Exception {
if (FacesContext.getCurrentInstance().isPostback()) {
return;
}
readFromDatabase();
}
private void readFromDatabase() {
//use _strID to read and set property
}
<f:event type="preRenderView">
不会在每个请求中被调用?它确实会在每个请求中被调用。 - BalusC<f:event type="preRenderView" listener="#{bean.onload}" />
在从onload
中删除@PostContruct
后访问视图参数。页面上有一个下拉菜单(非ajax,因为我打算在提交时提交更改)。在页面提交(重定向)时,该下拉列表的更改值重置为默认值(第一项),我可以看到下拉列表setter被调用两次。首先是用户所做的更改,其次是自动重置,如我所说。当我再次回到@PostConstruct
时,事情变得正常。Setter仅为用户最后选择调用一次。我该怎么办? - user2918640