我已将f:ajax
标记替换为未放入内联脚本的自制解决方案。它对actionButton
感到奇怪。但是我无法让panelGroup
的听众工作。原因是无法指定ajax请求产生的bean目标方法应该是什么。换句话说,使用commandButton
我可以在action
中指定目标bean方法,但panelGroup
没有这样的属性;因为我不想使用f:ajax listener
,我想替换它。
<h:commandButton data-widget="jsfajax" value="ajax" action="#{someAction}"/>
$(document).ready(function(){
(function(widgets){
document.body.addEventListener("click", function(e) {
var w = e.target.getAttribute("data-widget");
if(w){
e.preventDefault();
widgets[w](e.target);
}
});
})(new Widgets);
});
function Widgets(){
this.jsfajax = function jsfajax(elem){
if(elem.id == ""){
elem.id = elem.name;
}
mojarra.ab(elem,"click",'action','@form',0);
}
}
这很有效。
但这显然不会(确实没有,但它不会调用任何东西):
<h:panelGroup>
<f:passThroughAttribute name="data-widget" value="jsfajax"/>
Click here
</h:panelGroup>
但这样做:
<h:panelGroup>
<f:ajax event="click" listener="#{someAction}"/>
Click here
</h:panelGroup>
这两个panelGroup
都会产生相同的HTML输出,因此我假设它是“记住”该panelGroup上的点击链接到#{someAction}
的jsf容器。
我想要做的是在不使用f:ajax listener
的情况下重新创建该链接。目前我要使用一个不太优雅的隐藏commandButton。
也许是一个复合组件panelGroup,可以保存“动作链接”,我不知道。
答案 0 :(得分:0)
您希望实现的目标只能在UICommand
组件上实现,而不能在ClientBehaviorHolder
组件上实现。一种解决方案是创建一个扩展HtmlCommandLink
的自定义组件,该组件呈现<div>
而不是<a>
,并像<your:div action="#{bean.action}">
一样使用它。
最理想的解决方案是更换标准渲染器。例如。 <h:panelGorup>
:
<render-kit>
<renderer>
<component-family>javax.faces.Panel</component-family>
<renderer-type>javax.faces.Group</renderer-type>
<renderer-class>com.example.YourPanelGroupRenderer</renderer-class>
</renderer>
</render-kit>
基本上,这些渲染器应跳过渲染<f:ajax>
- 相关on*
属性,而是渲染您的data-widget
属性(最好还有其他属性代表现有<f:ajax>
属性,例如{ {1}},execute
,render
等)。您还应该针对标准API进行编程,而不是Mojarra特定的API。即直接使用delay
代替jsf.ajax.request()
快捷方式。
通过这种方式,您可以保持视图符合JSF标准。您和未来的开发人员在编写JSF代码时甚至不需要学习/思考“专有”API。您只需继续使用mojarra.ab()
即可。您只需通过webapp中的JAR插入自定义渲染和脚本,就可以了。 JAR甚至可以在所有其他现有的JSF应用程序上重用。它甚至可能变得流行,因为内联脚本确实被认为是不好的做法。
这只是一些代码,对于首发来说并不一定是微不足道的。
另一种方法是将标准响应编写器替换为自定义响应编写器,其中覆盖writeAttribute()
并检查属性名称是否以<h:panelGroup><f:ajax>
开头,然后按照您的想法处理它们。例如。解析它并编写不同的属性。这是一个启动示例,它也识别on
。
<h:panelGroup><f:ajax>
public class NoInlineScriptRenderKitFactory extends RenderKitFactory {
private RenderKitFactory wrapped;
public NoInlineScriptRenderKitFactory(RenderKitFactory wrapped) {
this.wrapped = wrapped;
}
@Override
public void addRenderKit(String renderKitId, RenderKit renderKit) {
wrapped.addRenderKit(renderKitId, renderKit);
}
@Override
public RenderKit getRenderKit(FacesContext context, String renderKitId) {
RenderKit renderKit = wrapped.getRenderKit(context, renderKitId);
return (HTML_BASIC_RENDER_KIT.equals(renderKitId)) ? new NoInlineScriptRenderKit(renderKit) : renderKit;
}
@Override
public Iterator<String> getRenderKitIds() {
return wrapped.getRenderKitIds();
}
}
public class NoInlineScriptRenderKit extends RenderKitWrapper {
private RenderKit wrapped;
public NoInlineScriptRenderKit(RenderKit wrapped) {
this.wrapped = wrapped;
}
@Override
public ResponseWriter createResponseWriter(Writer writer, String contentTypeList, String characterEncoding) {
return new NoInlineScriptResponseWriter(super.createResponseWriter(writer, contentTypeList, characterEncoding));
}
@Override
public RenderKit getWrapped() {
return wrapped;
}
}
您拥有自由的最重要部分是最后一个片段中的public class NoInlineScriptResponseWriter extends ResponseWriterWrapper {
private ResponseWriter wrapped;
public NoInlineScriptResponseWriter(ResponseWriter wrapped) {
this.wrapped = wrapped;
}
@Override
public ResponseWriter cloneWithWriter(Writer writer) {
return new NoInlineScriptResponseWriter(super.cloneWithWriter(writer));
}
@Override
public void writeAttribute(String name, Object value, String property) throws IOException {
if (name.startsWith("on")) {
if (value != null && value.toString().startsWith("mojarra.ab(")) {
super.writeAttribute("data-widget", "jsfajax", property);
}
}
else {
super.writeAttribute(name, value, property);
}
}
@Override
public ResponseWriter getWrapped() {
return wrapped;
}
}
方法。上面的启动示例只是盲目地检查writeAttribute()
属性值是否以Mojarra特定on*
开头,然后写入"mojarra.ab("
。换句话说,每一个(自然使用!)data-widget="jsfajax"
都将以这种方式重写。您可以继续使用<f:ajax>
和<h:commandLink><f:ajax>
自然方式。
<h:panelGroup><f:ajax>
属性。
要使其运行,请在<f:ajax>
:
faces-config.xml
您仍然需要考虑现有的特定于实现的细节(幸运的是,只有两个:Mojarra和MyFaces)。