【问题标题】:JSF Best Practice: Custom Components and JavaScriptJSF 最佳实践:自定义组件和 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;      
  }
}

【问题讨论】:

  • 你能发布你的组件吗? :) 只需要了解如何生成示例。
  • 如果您也需要渲染器或其他任何东西,请告诉我。

标签: javascript jsf custom-component taglib


【解决方案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 应用程序中的文件路径仍然冲突,它们将不会被包含在内。

另请参阅:

【讨论】:

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

【讨论】:

    猜你喜欢
    • 2011-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-19
    • 1970-01-01
    • 2017-03-10
    • 2014-03-20
    • 2012-08-03
    相关资源
    最近更新 更多