我遇到的问题是我的代码没有触发我的支持bean中的操作。代码如下:
HtmlCommandButton replyCommentButton = new HtmlCommandButton();
replyCommentButton.setId("replyCommentButton" + commentCounter);
replyCommentButton.setValue("Create reply");
String action = "#{Handler.action_replyToComment}";
MethodExpression methodExpression =
FacesContext.getCurrentInstance().getApplication().getExpressionFactory().
createMethodExpression(FacesContext.getCurrentInstance().getELContext(), action, null,
new Class<?>[0]);
replyCommentButton.setActionExpression(methodExpression);
在我的名为RequestHandlerBean的支持bean中,在FacesConfig中定义为Handler,我有以下代码:
public void action_replyToComment() {
logger.info("Homemade action called!!!");
System.out.println("Homemade action called!!!");
}
当我点击按钮时,有没有人发现为什么没有发生?它没有正确触发事件。 html代码的来源如下:
<input id="replyCommentButton1" type="submit" value="Create reply"
name="replyCommentButton1"/>
正如我们所看到的,HTML中没有定义任何操作。
编辑2:我刚刚在Javadoc中发现我的action方法必须是一个公共String。我现在在我的支持bean中更改了这个,所以我的支持bean中的代码是:
public String action_replyToComment() {
logger.info("Homemade action called!!!");
System.out.println("Homemade action called!!!");
return null;
}
Edit2:我还确保将其封装在标签中,但仍然没有运气。不应该在元素上有action属性吗?
编辑3:我的bean在我的faces-config中定义如下:
<managed-bean>
<description>
Handles the specific request.
</description>
<managed-bean-name>Handler</managed-bean-name>
<managed-bean-class>no.ngt.tech.rt2.beans.RequestHandlerBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
此外,如果我选择在我的JSF页面中输出:
<a4j:commandButton action="#{Handler.action_replyToComment}" value="Reply" />
完美无缺
编辑4 - 我的JSP页面 注意我现在也尝试使用折旧的setAction(methodBinding),但遗憾的是它也没有用。
<%@ include file="_includes.jsp" %>
<f:view>
<html>
<head>
<title><h:outputText value="#{msgs.title}" /></title>
</head>
<body>
<br /><br /><br />
<%@ include file="_menu.jsp" %>
<rich:tabPanel switchType="client">
<rich:tab id="commentsTab" label="Comments" rendered="#{Handler.editRequest}">
<h:form>
<ngt:commentTree binding="#{Handler.commentTree}" value="#{Handler.comments}" />
<br />
<a4j:commandButton action="#{Handler.action_replyToComment}" value="testbutton" />
</h:form>
</rich:tab>
</rich:tabPanel>
</body>
</html>
</f:view>
引入了menu.jsp:
<h:form>
<rich:toolBar itemSeparator="line" styleClass="toolbar" contentClass="toolbar" height="22">
<rich:toolBarGroup>
<rich:menuItem submitMode="server" value="Front" action="#{newRT.action_showFront}" />
</rich:toolBarGroup>
<rich:toolBarGroup>
<rich:menuItem submitMode="server" value="New request" action="#{Step.action_showSteps}" />
</rich:toolBarGroup>
<rich:toolBarGroup>
<rich:menuItem submitMode="server" value="Requests" action="#{Handler.action_showRequestsView}" />
</rich:toolBarGroup>
<rich:toolBarGroup>
<rich:menuItem submitMode="server" value="Control-panel" action="#" />
</rich:toolBarGroup>
<rich:toolBarGroup location="right">
<h:inputText styleClass="barsearch" value="#{Handler.search}" />
<a4j:commandButton styleClass="barsearchbutton" action="#{Handler.action_GetRequestFromID}" value="Search" />
</rich:toolBarGroup>
</rich:toolBar>
</h:form>
<br/><br/>
Includes.jsp
<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>
<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="a4j" uri="http://richfaces.org/a4j" %>
<%@ taglib prefix="rich" uri="http://richfaces.org/rich"%>
<%@ taglib prefix="ngt" uri="http://MySpecialTagLib.no/"%>
编辑7 - UIComponent的Java代码:
这是CommentsTreeUI.java:
public class CommentsTreeUI extends UIOutput {
private static Logger logger = Logger.getLogger(CommentsTreeUI.class.getName());
@Override
public void encodeBegin(FacesContext context) throws IOException {
List<CommentTag> value = (List<CommentTag>) getAttributes().get("value");
int commentCounter = 0;
if (value != null) {
for (CommentTag comment : value) {
commentCounter++;
ResponseWriter commentContainerWriter = context.getResponseWriter();
commentContainerWriter.startElement("div", this);
commentContainerWriter.writeAttribute("id", "Comment" + commentCounter, null);
String width = comment.getWidth();
String height = comment.getHeight();
String style = comment.getStyle();
style = (style != null) ? style + ";" : "";
if (width != null) {
style += "width:" + width + ";";
}
if (height != null) {
style += "height:" + height + ";";
}
commentContainerWriter.writeAttribute("style", style, null);
String newComment = comment.getNewComment();
if (newComment == null) {
newComment = "false";
}
String level = comment.getLevel();
if (level != null) {
level = "commentContainerLevel" + level + newComment;
}
commentContainerWriter.writeAttribute("class", level, null);
String title = comment.getTitle();
if (title != null) {
commentContainerWriter.writeAttribute("title", title, null);
}
String titleText = comment.getTitleText();
if (titleText != null) {
ResponseWriter titleTextWriter = context.getResponseWriter();
UIOutput titleTextComponent = new UIOutput();
titleTextWriter.startElement("div", titleTextComponent);
titleTextWriter.writeAttribute("class", "commentHeaderText" + newComment, null);
titleTextWriter.writeText(titleText + " | ", null);
titleTextWriter.startElement("a", titleTextComponent);
titleTextWriter.writeAttribute("onclick", "showCommentReply('CommentReply" + commentCounter + "')", null);
titleTextWriter.writeAttribute("class", "reply", null);
titleTextWriter.writeText("Reply", null);
titleTextWriter.endElement("a");
titleTextWriter.endElement("div");
}
String commentBody = comment.getCommentBody();
if (commentBody != null) {
ResponseWriter commentBodyWriter = context.getResponseWriter();
UIOutput commentBodyComponent = new UIOutput();
commentBodyWriter.startElement("div", commentBodyComponent);
commentBodyWriter.writeText(commentBody, null);
commentBodyWriter.endElement("div");
}
ResponseWriter replyContainerWriter = context.getResponseWriter();
UIOutput replyContainerComponent = new UIOutput();
replyContainerWriter.startElement("div", replyContainerComponent);
commentContainerWriter.writeAttribute("id", "CommentReply" + commentCounter, null);
replyContainerWriter.writeAttribute("class", "replyContainer", null);
ResponseWriter replyHeaderWriter = context.getResponseWriter();
UIOutput replyHeaderComponent = new UIOutput();
replyHeaderWriter.startElement("div", replyHeaderComponent);
replyHeaderWriter.writeAttribute("class", "replyHeaderContainer", null);
replyHeaderWriter.endElement("div");
ResponseWriter replyFormWriter = context.getResponseWriter();
UIInput replyFormComponent = new UIInput();
replyFormWriter.startElement("fieldset", replyFormComponent);
replyFormWriter.startElement("textarea", replyFormComponent);
replyFormWriter.writeAttribute("type", "textarea", null);
replyFormWriter.writeAttribute("rows", "5", null);
replyFormWriter.writeAttribute("cols", "76", null);
replyFormWriter.writeText("Write your answer here", null);
replyFormWriter.endElement("textarea");
//TODO: Fix so button has action to backing bean
HtmlAjaxCommandButton replyCommentButton = new HtmlAjaxCommandButton();
replyCommentButton.setId("replyCommentButton" + commentCounter);
replyCommentButton.setValue("Create reply");
String action = "#{RequestHandlerBean.action_replyToComment}";
//replyCommentButton.setReRender("commentsTree");
ExpressionFactory factory = context.getApplication().getExpressionFactory();
Class [] argtypes=new Class[1];
argtypes[0]=ActionEvent.class;
MethodExpression replyActionExpression = factory.createMethodExpression(context.getELContext(), action, null, argtypes);
replyCommentButton.setActionExpression(replyActionExpression);
MethodExpression methodExpression = context.getCurrentInstance().getApplication().getExpressionFactory().
createMethodExpression(context.getCurrentInstance().getELContext(), action, null, new Class<?>[0]);
replyCommentButton.setActionExpression(methodExpression);
/*
replyCommentButton.setAction(context.getApplication().createMethodBinding(action, argtypes));
*/
replyCommentButton.encodeAll(context);
//Todo above
replyFormWriter.writeText(" ", null);
replyFormWriter.startElement("input", replyFormComponent);
replyFormWriter.writeAttribute("type", "button", null);
replyFormWriter.writeAttribute("value", "Cancel ", null);
replyFormWriter.writeAttribute("onclick", "hideCommentReply('CommentReply" + commentCounter + "')", title);
replyFormWriter.endElement("input");
replyFormWriter.endElement("fieldset");
replyContainerWriter.endElement("div");
commentContainerWriter.endElement("div");
}
} else { //value==null
ResponseWriter writer = context.getResponseWriter();
writer.startElement("div", this);
writer.writeAttribute("id", getClientId(context), null);
String width = (String) getAttributes().get("width");
String height = (String) getAttributes().get("height");
String style = (String) getAttributes().get("style");
style = (style != null) ? style + ";" : "";
if (width != null) {
style += "width:" + width + ";";
}
if (height != null) {
style += "height:" + height + ";";
}
writer.writeAttribute("style", style, null);
String styleClass = (String) getAttributes().get("styleClass");
if (styleClass != null) {
writer.writeAttribute("class", styleClass, null);
}
String title = (String) getAttributes().get("title");
if (title != null) {
writer.writeAttribute("title", title, null);
}
}
}
@Override
public void encodeEnd(FacesContext context) throws IOException {
ResponseWriter writer = context.getResponseWriter();
writer.endElement("div");
}
这是CommenstTreeTag:
public class CommentsTreeTag extends UIComponentTag {
String style;
String styleClass;
String title;
String width;
String height;
String value;
Long parentId;
public void release() {
// the super class method should be called
super.release();
style = null;
styleClass = null;
title = null;
height = null;
width = null;
parentId = null;
value = null;
}
@Override
protected void setProperties(UIComponent component) {
// the super class method should be called
super.setProperties(component);
if (style != null) {
component.getAttributes().put("style", style);
}
if (styleClass != null) {
component.getAttributes().put("styleClass", styleClass);
}
if (width != null) {
component.getAttributes().put("width", width);
}
if (height != null) {
component.getAttributes().put("height", height);
}
if (title != null) {
if (isValueReference(title)) {
ValueBinding vb =
getFacesContext().getApplication().createValueBinding(title);
component.setValueBinding("title", vb);
} else {
component.getAttributes().put("title", title);
}
}
if (value != null) {
if (isValueReference(value)) {
ValueBinding vb =
getFacesContext().getApplication().createValueBinding(value);
component.setValueBinding("value", vb);
getFacesContext().getApplication().createValueBinding(value);
} else {
component.getAttributes().put("value", value);
}
}
if (parentId != null) {
component.getAttributes().put("parentId", parentId);
}
}
public String getComponentType() {
return "commentTree";
}
public String getRendererType() {
// null means the component renders itself
return null;
}
public String getHeight() {
return height;
}
public void setHeight(String height) {
this.height = height;
}
public String getWidth() {
return width;
}
public void setWidth(String width) {
this.width = width;
}
public String getStyle() {
return style;
}
public void setStyle(String style) {
this.style = style;
}
public String getStyleClass() {
return styleClass;
}
public void setStyleClass(String styleClass) {
this.styleClass = styleClass;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
答案 0 :(得分:3)
我认为您遇到的问题是由于您在JSF组件树中添加commandButton的方式,或者更准确地说,是您不在组件树中添加它的方式。
由于未将commandButton附加到JSF组件树,因此在呈现此组件时(通过调用.encodeAll()方法),它不会找到嵌套此组件的表单。 因此,HTML输入无法正确创建。
也许你可以在要求渲染之前尝试直接添加创建到窗体的commandButton。您可以使用以下代码执行此操作:
// Search for the component HtmlForm that is a (in)direct parent of the current component
private UIComponent getCurrentForm(UIComponent currentComponent) {
UIComponent parent = currentComponent.getParent();
while ((parent != null) && !(parent instanceof HtmlForm)) {
parent = parent.getParent();
}
return parent;
}
public void encodeBegin(FacesContext context) throws IOException {
...
HtmlAjaxCommandButton replyCommentButton = new HtmlAjaxCommandButton();
...
// Add the command button in the form that contains your custom component...
UIComponent form = getCurrentForm(this);
if (form != null) {
form.getChildren().add(replyCommentButton);
}
replyCommentButton.encodeAll(context);
...
}
请注意我已经测试了这段代码,所以也许你需要修改一下......
如果它仍然不起作用,也许你需要检查你的代码,以便在render类之外或encodeBegin之外创建commandButton ...我不认为修改JSF是个好主意渲染阶段的组件树......
答案 1 :(得分:1)
您的代码似乎是正确的(实际上,该方法必须返回一个String,但它也可以返回void,即使不建议写这样的动作方法)。
您确定创建的commandButton是否嵌套在组件中?否则,它将无法正常工作。 通过这种方式,我的意思是(在Java或JSF页面中创建,无论如何),必须具有直接或间接父(在JSF组件树中)一个组件。例如:
<h:form>
...
<h:commandButton .../>
...
</h:form>
单击问题时是否有任何Javascript错误?
关于评论的修改。
编辑2,关于我对主帖的评论:
也许您可以尝试使用旧方法将操作附加到按钮上(好吧,它已被弃用,但只是尝试一下):
replyCommandButton.setAction(context.getApplication().createMethodBinding("#{Handler.action_replyToComment}", null));