我想用标签创建 JSF 页面。像这样的东西。但是我想知道如果我选择使用 Jquery 来执行此操作,我可以实现延迟加载 - 当我单击 JSF 页面上的选项卡时,会在打开选项卡时生成内容。是否可以在纯 JSF 中实现选项卡的延迟加载?而且我想在这两种情况下我都可以轻松实现 AJAX。
最良好的祝愿
Primefaces Tabview组件支持延迟加载。
来自展示柜的引述:
选项卡内容也可以使用 ajax 延迟加载,当动态属性设置为“true”时,只会呈现活动选项卡的内容,单击惰性选项卡将使用 ajax 获取选项卡内容。在处理具有大量内容的选项卡时,此行为可以方便地节省带宽并减小页面大小。
展示中的快速示例:
<h:form id="form">
<p:tabView id="tabView" dynamic="true" cache="true">
// tabs
</p:tabView>
</h:form>
如果您在选项卡之间切换,该cache
属性用于防止 ajax 重新加载选项卡内容。
注意:如果您希望您的选项卡 bean 成为会话范围,请阅读答案底部的说明...
由于您不想使用任何第三方库,这里有一个 PureJSF + jQuery 示例
JSF + Jquery + Ajax 延迟加载 + 查看 Scope Beans 示例...
顺便说一句,这是最终的样子:
您可以查看 Web 服务器控制台的打印输出@PostConstruct
以及@PreDestroy
单击每个选项卡时...
选项卡的内容 - xhtml 页面及其 bean 将在选项卡单击(延迟加载)时加载,并在单击其他选项卡时被销毁,
我建议您创建一个新项目并慢慢将所有文件放入其中并开始播放并查看它......它 100% 工作,但我放置了一些打印输出只是为了看看它真的工作......
这个例子非常简单直接......
并放置jquery-1.7.1_.min.js
并jquery-ui-1.8.18.custom.min.js
在WebContent\resources\js
其中jquery-ui-1.8.18.custom.css
WebContent\resources\css
现在到其他文件...
myTabs.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:head>
<h:outputScript library="js" name="jquery-1.7.1_.min.js" target="head" />
<h:outputScript library="js" name="jquery-ui-1.8.18.custom.min.js" target="head" />
<h:outputStylesheet library="css" name="jquery-ui-1.8.18.custom.css" target="head" />
<h:outputScript library="js" name="mytabs.js" target="head" />
</h:head>
<h:body>
<f:view>
<h:form prependId="false">
<h:panelGroup id="tabs" layout="block">
<ul>
<c:forEach items="#{myTabs.tabs}" var="tab">
<li><a href="##{tab.tabid}" onclick="$('#button_#{tab.tabid}').click()">#{tab.tabid}</a></li>
<h:commandButton id="button_#{tab.tabid}" value="TabClick" action="#{myTabs.switchPages(tab.tabid)}" style="display:none">
<f:ajax render="tabs"></f:ajax>
</h:commandButton>
</c:forEach>
</ul>
<c:forEach items="#{myTabs.tabs}" var="tab">
<h:panelGroup id="#{tab.tabid}" layout="block" rendered="#{tab.tabid eq myTabs.selectedTab}">
<ui:include src="#{tab.tabfilename}"></ui:include>
</h:panelGroup>
</c:forEach>
</h:panelGroup>
</h:form>
</f:view>
</h:body>
</html>
MyTabs.java
package pack;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
@ManagedBean
@SessionScoped
public class MyTabs{
@PostConstruct
public void init(){
tabs = new ArrayList<MyTabObject>();
tabs.add(new MyTabObject("tab1.xhtml", "tab1"));
tabs.add(new MyTabObject("tab2.xhtml", "tab2"));
tabs.add(new MyTabObject("tab3.xhtml", "tab3"));
}
String selectedTab="tab1";
public String getSelectedTab() {
return selectedTab;
}
public void setSelectedTab(String selectedTab) {
this.selectedTab = selectedTab;
}
public String switchPages(String selTab) {
selectedTab = selTab;
return "myTabs.xhtml";
}
List<MyTabObject> tabs;
public List<MyTabObject> getTabs() {
return tabs;
}
public void setTabs(List<MyTabObject> tabs) {
this.tabs = tabs;
}
}
我的标签对象
package pack;
public class MyTabObject{
String tabfilename;
String tabid;
public String getTabfilename() {
return tabfilename;
}
public void setTabfilename(String tabfilename) {
this.tabfilename = tabfilename;
}
public String getTabid() {
return tabid;
}
public void setTabid(String tabid) {
this.tabid = tabid;
}
public MyTabObject(String tabfilename, String tabid) {
super();
this.tabfilename = tabfilename;
this.tabid = tabid;
}
}
Tab1Page ,(Tab2Page 和 Tab3Page 完全一样,只是把所有地方的数字都改了)
package pack;
import java.io.Serializable;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
@ManagedBean
@ViewScoped
public class Tab1Page implements Serializable{
/**
*
*/
private static final long serialVersionUID = 254415216070877770L;
// Constants
public final static String hashKey = "tab1PageTab";
public String actionString = "";
@PostConstruct
public void post(){
Format formatter;
Date date = new Date();
// Time formate 01:12:53 AM
formatter = new SimpleDateFormat("hh:mm:ss a");
tabName = formatter.format(date);
System.out.println("Tab1Page\t"+tabName+"\t@PostConstruct...");
}
@PreDestroy
public void destroy(){
Format formatter;
Date date = new Date();
// Time formate 01:12:53 AM
formatter = new SimpleDateFormat("hh:mm:ss a");
tabName = formatter.format(date);
System.out.println("Tab1Page\t"+tabName+"\t@PreDestroy...");
}
String tabName;
public String getTabName() {
return this.getClass().getName().substring(this.getClass().getName().lastIndexOf("."))+"\t"+tabName;
}
public void setTabName(String tabName) {
this.tabName = tabName;
}
public String getActionString() {
return actionString;
}
public void setActionString(String actionString) {
this.actionString = actionString;
}
}
tab1.xhtml (tab2.xhtml 和 tab3.xhtml 完全一样 - 只是替换数字)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:panelGroup>
<h:form>
<h:outputText value="#{tab1Page.tabName}" />
</h:form>
</h:panelGroup>
</ui:composition>
到最后一个文件
mytabs.js(将其放在 WebContent\resources\js 中)
$(document).ready(function () {
$("#tabs").tabs();
});
$(window).load(function() {
jsf.ajax.addOnEvent(function (data) {
if (data.status === "success") {
$("#tabs").tabs();
}
});
});
为了使用会话范围 Bean:
switchPages
中的方法MyTabs.java
应该是void
而不是返回任何东西,像这样
public void switchPages(String selTab) {
selectedTab = selTab;
}
使用 jQuery UI 实现 ajax 选项卡根本不是问题。
在此处查看带有 ajax 的 jQuery Tabs 的文档,然后单击“查看源代码”以查找您需要的代码。
您可以查看书籍 CoreJava Server Faces third edition
第 339 页,了解如何使用h:panelGrid
.
输出是这样的:
这是书中的代码示例:
...
<h:form>
<h:panelGrid styleClass="tabbedPane" columnClasses="displayPanel">
<!-- Tabs -->
<f:facet name="header">
<h:panelGrid columns="4" styleClass="tabbedPaneHeader">
<h:commandLink tabindex="1"
title="#{msgs.jeffersonTooltip}"
styleClass="#{tp.jeffersonStyle}"
actionListener="#{tp.jeffersonAction}">
#{msgs.jeffersonTab}
</h:commandLink>
...
</h:panelGrid>
</f:facet>
<!-- Tabbed pane content -->
<ui:include src="washington.xhtml" />
<ui:include src="roosevelt.xhtml" />
<ui:include src="lincoln.xhtml" />
<ui:include src="jefferson.xhtml" />
</h:panelGrid>
</h:form>
...
这是描述:
The tabbed pane is implemented with h:panelGrid. Because we do not specify
the columns attribute, the panel has one column. The panel’s header—defined
with an f:facet tag—contains the tabs, which are implemented with another
h:panelGrid that contains h:commandLink tags for each tab. The only row in the panel
contains the content associated with the selected tab.
When a user selects a tab, the associated action listener for the command link is
invoked and modifies the data stored in the backing bean. Because we use a
different CSS style for the selected tab, the styleClass attribute of each h:commandLink
tag is pulled from the backing bean with a value reference expression.
As you can see from the top picture in Figure 8–11, we have used the title
attribute to associate a tooltip with each tab. Another accessibility feature is the
ability to move from one tab to another with the keyboard instead of the
mouse. We implemented that feature by specifying the tabindex attribute for
each h:commandLink.
The content associated with each tab is statically included with the JSP include
directive. For our application, that content is a picture and some text, but
you could modify the included JSF pages to contain any set of appropriate
components. Notice that even though all the JSF pages representing content are
included, only the content associated with the current tab is rendered. That is
achieved with the rendered attribute—for example, jefferson.xhtml looks like this:
Putting It All Together
<h:panelGrid columns="2" columnClasses="presidentDiscussionColumn"
rendered="#{tp.jeffersonCurrent}">
<h:graphicImage value="/images/jefferson.jpg"/>
<span class="tabbedPaneContent">"#{msgs.jeffersonDiscussion}"</span>
</h:panelGrid>
Figure 8–12 shows the directory structure for the tabbed pane application and
Listings 8–14 through 8–17 show the most important files.
不幸的是,我不知道如何在这段代码中添加延迟加载和 AJAX 支持。