JSF最佳实践:自定义组件和JavaScript

5
我正在开发一个JSF自定义组件,使用以下书籍中找到的信息:Pro JSF and HTML5 by Apress
到目前为止,我已经成功地开发了:
- 用于获取要在组件中呈现的数据的Java类 - Java组件类 - Java渲染器类 - taglib文件 - 用于呈现taglib的示例页面
一切运行良好,组件成功呈现。
现在,我想为呈现的元素添加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;      
  }
}

你能发布你的组件吗? :) 我只需要一个生成示例的想法。 - Josef E.
如果你需要渲染器或其他什么东西,请告诉我。 - INElutTabile
2个回答

1

您可以通过添加以下代码将外部JavaScript文件包含到使用您组件的Facelets中:

    <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
    });
    });

1
如果您希望使组件可重用,我建议您将所有内容打包到独立的jar文件中。如果使用Servlet 3.0,则可以将Web资源放置在中以便轻松访问。为该jar文件提供,这样它就可以被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应用程序中的路径冲突,则不会包含它们。

另请参阅:


2
@Biker我正在使用自定义组件,而不是复合组件,所以我想我不应该创建“comp”目录,对吗?关于JS事件:HTML的渲染是由一个Java类执行的,而不是像复合组件那样由一个xhtml页面执行,将一个JS事件附加到Java渲染器类中的元素,并在一个JS文件中处理它的函数是否常见(或者说做得很好)? - INElutTabile
@INElutTabile,这个布局让您决定如何实现您的组件。组合组件只是为其声明添加了一个xhtml视图层,因此如果您只想使用Java代码,那么您可以,因为使用组合可以使用自定义组件来完成的所有内容也可以完成。我推断您正在使用该框架,因为对于这样的行为使用自定义组件对我来说会过度,特别是当JSF 2.x可用时。这里有一些相关链接:http://bit.ly/1lP5mKs http://bit.ly/VCPIIx - Aritz
1
@Biker 感谢您的帮助!我希望您可以在您的回答中添加另一个重要的(在我看来)细节。我知道我需要使用的每个 JS 资源都必须包含在我的页面中以便使用。我正在使用一个 Java 渲染器类,我想我必须在这样的类中包含 js 资源才能使用它。对吗?将我的 js 资源包含在渲染器类中并进行写入,例如 'responseWriter.write("<script src .... ");',这样做正确吗? - INElutTabile
@Biker 对于你上一个问题的回答,我正在使用自定义组件,因为我处理的是可以有n级子菜单的动态菜单,所以我需要对菜单项进行递归渲染。我想正确的选择是使用Java渲染器 :) - INElutTabile
1
@INElutTabile 不客气;-) 我在自定义渲染器方面经验不多,基本上我从来没有自己实现过一个。但是,是的,我认为你用 responseWriter 是正确的方式。关于你关于动态菜单的陈述,没有必要使用自定义渲染器+非Facelets。那太过了。使用组合,它们也可以由自定义组件支持,并且可能有与之相关联的Facelet(视图)。您可以在组件中为菜单设置结构,并在视图中使用 ui:repeat 进行迭代,以实现您想要的功能。 - Aritz
1
顺便说一句,你想做的事情已经被实现了(http://www.primefaces.org/showcase/ui/menu/menu.xhtml)。你想不想自己动手实现就是另外一回事了;-) - Aritz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接