JSF 最佳实践:自定义组件和 JavaScript
Posted
技术标签:
【中文标题】JSF 最佳实践:自定义组件和 JavaScript【英文标题】:JSF Best Practice: Custom Components and JavaScript 【发布时间】:2014-08-22 00:58:46 【问题描述】:我正在开发一个 JSF 自定义组件,使用我在以下书籍 Pro JSF and html5 by Apress 中找到的信息。
到目前为止,我成功开发了:
获取要在组件中渲染的数据的java类 java 组件类 java 渲染器类 标签库文件 呈现标签库的示例页面一切正常,组件渲染成功。
现在我想为渲染的元素添加javascript事件和行为,更具体地说,我的自定义组件的目的是在网页上渲染一个菜单,我想广告菜单项的下拉效果。我知道如何用 JavaScript 编写整个代码,但我不知道的是:
向自定义组件中呈现的元素添加 javascript 事件和行为的最佳做法是什么?
JS文件应该放在哪里?如何将事件绑定到元素?是在渲染类中完成,还是在网页上完成?
谢谢,如果需要,我愿意提供有关我的代码的更具体信息。
Java 组件类
注意: CosmoMenu 类只是一个 bean。它基本上存储了一个菜单树(一个标签、一个 id 和一组子项,如果有的话)。
package components;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import domain.CosmoMenu;
import javax.faces.component.FacesComponent;
import javax.faces.component.UIComponentBase;
@FacesComponent(CosmoMenuComponent.COMPONENT_TYPE)
public class CosmoMenuComponent extends UIComponentBase
/** Component family of @link CosmoMenuComponent. */
public static final String COMPONENT_FAMILY = "CosmoMenu";
/** Component type of @link CosmoMenuComponent. */
public static final String COMPONENT_TYPE = "CosmoMenu";
@Override
public String getFamily()
return CosmoMenuComponent.COMPONENT_FAMILY;
private CosmoMenu theMenu;
public CosmoMenu getMenu()
Gson gson = new Gson();
JsonParser jsonParser = new JsonParser();
CosmoMenuAPI myApi = new CosmoMenuAPI();
String strMenu = myApi.getMenu();
JsonElement jEl = jsonParser.parse(strMenu);
theMenu = gson.fromJson(jEl, CosmoMenu.class);
return theMenu;
【问题讨论】:
你能发布你的组件吗? :) 只需要了解如何生成示例。 如果您也需要渲染器或其他任何东西,请告诉我。 【参考方案1】:如果您希望您的组件可重复使用,我鼓励您将所有内容打包在一个独立的 jar 中。如果使用 Servlet 3.0,您将能够轻松访问将它们放在 META-INF/resources 中的 Web 资源。为 jar 提供一个 faces-config.xml,您将使其 JSF 注释可扫描:
components
\-(Your cource code)
META-INF
\-faces-config.xml
\-resources (This ends up in docroot)
\-resources
\-js (Here they go your js files)
\-comp (Here your composite components)
\-css (Here your css)
稍后,您将不得不注意避免复合中的特定 ID,因为 JSF 在渲染时会修改它们。您最好将当前组件引用传递给您的 JS 函数:
<h:inputText styleClass="myInputStyle" onclick="showInputText(this)" />
只需参考包含的 CSS 样式和 JS 函数即可。
最后但同样重要的是,在将 jar 包含为 Web 资源时要小心,如果文件路径与您的 Web 应用程序中的文件路径仍然冲突,它们将不会被包含在内。
另请参阅:
Exposing resources from jar files in web applications (Tomcat7) How to reference JSF managed beans which are provided in a JAR file? How can I know the id of a JSF component so I can use in Javascript【讨论】:
@Biker 我正在使用自定义组件,而不是复合组件,我认为我不应该创建“comp”目录,对吧?关于 JS 事件:HTML 的呈现由 java 类执行,而不是由 xhtml 页面(如在复合组件中)执行,将 JS 事件附加到 java 渲染器类中的元素是否常见(或做得很好) ,由 JS 文件中的函数处理? @INElutTabile,这个布局让你决定如何实现你的组件。复合组件只需为其声明添加一个 xhtml 视图层,因此如果您只想使用 java 代码,您可以,因为复合组件可以实现的所有功能也可以使用自定义组件完成。我推断您正在使用该框架,因为使用自定义组件来实现这种行为对我来说太过分了,而且当 JSF 2.x 可用时。这里有一些相关链接:bit.ly/1lP5mKsbit.ly/VCPIIx @Biker 感谢您的帮助!如果可以的话,我希望您在答案中添加另一个重要的(恕我直言)细节。我知道我需要的每个 JS 资源都必须包含在我的页面中,才能使用。我正在使用 Java 渲染器类,我想我必须在此类中包含 js 资源才能使用它。正确的?在渲染器类中执行写入是否正确,包括我的 js 资源,例如 'responseWriter.write(" @INElutTabile 不客气 ;-) 我对自定义渲染器的经验很少,基本上我从来没有自己实现过。但是,是的,我认为您使用responseWriter
的方式是正确的。关于您与动态菜单相关的声明,无需使用自定义渲染器+ no-facelets。那是矫枉过正。与复合材料一起使用,它们也可以由自定义组件支持,并且可能具有关联的 facelet(视图)。您可以实现您想要的,只需在组件中为您的菜单设置一个结构,并在您的视图中使用 ui:repeat
对其进行迭代。
顺便说一句,你想做的已经been implemented了。你是否想DIY是另一回事;-)【参考方案2】:
您可以通过添加以下代码在使用您的组件的 facelets 中包含一个外部 javascript 文件:
<script src="#request.contextPath/jspath/yourjs.js"></script>
当您生成 XHTML 输出时,在组件内为您的菜单条目提供一个 Id,例如
<h:outputText id="myid" value="#bean.value"/>
在你的js.js中
$(document).ready(function()
$("#myid").click(function()
// dostuff
);
);
【讨论】:
以上是关于JSF 最佳实践:自定义组件和 JavaScript的主要内容,如果未能解决你的问题,请参考以下文章