如果在嵌套复合组件中使用,#{cc} 正在解决 omnifaces 树中的错误
#{cc} is resolving wrong in omnifaces tree if used in nested composite components
参见以下简化代码:
test.xhtml
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:o="http://omnifaces.org/ui"
xmlns:test="http://xmlns.jcp.org/jsf/composite/test">
<body>
<h:form>
<h1>Nested - not working</h1>
<test:parentComp />
<h1>Not nested - working</h1>
<o:tree value="#{testModel.treeModel}">
<o:treeNode>
<ul>
<o:treeNodeItem>
<test:childComp />
<o:treeInsertChildren />
</o:treeNodeItem>
</ul>
</o:treeNode>
</o:tree>
</h:form>
</body>
</html>
parentComp.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:o="http://omnifaces.org/ui"
xmlns:cc="http://xmlns.jcp.org/jsf/composite"
xmlns:test="http://xmlns.jcp.org/jsf/composite/test">
<cc:interface componentType="parentComp">
</cc:interface>
<cc:implementation>
<div id="#{cc.clientId}">
<o:tree value="#{cc.treeModel}">
<o:treeNode>
<ul>
<o:treeNodeItem>
<test:childComp />
<o:treeInsertChildren />
</o:treeNodeItem>
</ul>
</o:treeNode>
</o:tree>
</div>
</cc:implementation>
</html>
childComp.xhtml
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:cc="http://xmlns.jcp.org/jsf/composite"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<cc:interface componentType="childComp">
</cc:interface>
<cc:implementation>
<div id="#{cc.clientId}">
<h:commandLink action="#{cc.childAction}" value="Click" />
</div>
</cc:implementation>
</html>
ParentComponent.java
@FacesComponent("parentComp")
public class ParentComponent extends UINamingContainer {
private TreeModel treeModel;
public ParentComponent() {
this.treeModel = new ListTreeModel();
this.treeModel.addChild("1").addChild("1.1");
this.treeModel.addChild("2").addChild("2.2");
}
public TreeModel getTreeModel() {
return treeModel;
}
}
ChildComponent.java
@FacesComponent("childComp")
public class ChildComponent extends UINamingContainer {
public void childAction() {
}
}
TestModel.java
@RequestScoped
@Named
public class TestModel {
private TreeModel treeModel;
public TestModel() {
this.treeModel = new ListTreeModel();
this.treeModel.addChild("1").addChild("1.1");
this.treeModel.addChild("2").addChild("2.2");
}
public TreeModel getTreeModel() {
return treeModel;
}
}
示例中复合组件中使用了o:tree,子组件的#{cc}解析错误,点击link会得到一个像这样的异常:
Caused by: javax.el.MethodNotFoundException: /resources/test/childComp.xhtml @10,71 action="#{cc.childAction}": Method not found: ParentComponent@422dcfd4.childAction()
如果 o:tree 没有像第二个示例那样嵌套在复合组件中,命令 link 将按预期工作。
这是 Omnifaces 中的错误吗?我是不是做错了什么?
这确实是 OmniFaces 中的一个错误。我在 this commit 中修复了它,修复程序在今天的 2.3 快照中可用(2.3 最终版本预计在本周结束,所以你很准时)。
原因是,排队的动作事件基本上是 caught and wrapped by <o:tree>
以便它可以记住当前迭代的树节点,它被触发。但是,在广播动作事件时,它是在 <o:tree>
本身上调用的,而不是在源组件(您的命令 link)上调用的。因此,只有 <o:tree>
上下文中的 #{cc}
本身才被视为复合组件父级。
我通过 pushing 将源组件自己的复合组件父级(如果有)修复到 EL 上下文中。
Original Tree#broadcast()
method:
wrapped.getComponent().broadcast(wrapped);
Fixed Tree#broadcast()
method:
UIComponent source = wrapped.getComponent();
pushComponentToEL(context, getCompositeComponentParent(source));
try {
source.broadcast(wrapped);
}
finally {
popComponentFromEL(context);
}
感谢您的举报!
参见以下简化代码:
test.xhtml
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:o="http://omnifaces.org/ui"
xmlns:test="http://xmlns.jcp.org/jsf/composite/test">
<body>
<h:form>
<h1>Nested - not working</h1>
<test:parentComp />
<h1>Not nested - working</h1>
<o:tree value="#{testModel.treeModel}">
<o:treeNode>
<ul>
<o:treeNodeItem>
<test:childComp />
<o:treeInsertChildren />
</o:treeNodeItem>
</ul>
</o:treeNode>
</o:tree>
</h:form>
</body>
</html>
parentComp.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:o="http://omnifaces.org/ui"
xmlns:cc="http://xmlns.jcp.org/jsf/composite"
xmlns:test="http://xmlns.jcp.org/jsf/composite/test">
<cc:interface componentType="parentComp">
</cc:interface>
<cc:implementation>
<div id="#{cc.clientId}">
<o:tree value="#{cc.treeModel}">
<o:treeNode>
<ul>
<o:treeNodeItem>
<test:childComp />
<o:treeInsertChildren />
</o:treeNodeItem>
</ul>
</o:treeNode>
</o:tree>
</div>
</cc:implementation>
</html>
childComp.xhtml
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:cc="http://xmlns.jcp.org/jsf/composite"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<cc:interface componentType="childComp">
</cc:interface>
<cc:implementation>
<div id="#{cc.clientId}">
<h:commandLink action="#{cc.childAction}" value="Click" />
</div>
</cc:implementation>
</html>
ParentComponent.java
@FacesComponent("parentComp")
public class ParentComponent extends UINamingContainer {
private TreeModel treeModel;
public ParentComponent() {
this.treeModel = new ListTreeModel();
this.treeModel.addChild("1").addChild("1.1");
this.treeModel.addChild("2").addChild("2.2");
}
public TreeModel getTreeModel() {
return treeModel;
}
}
ChildComponent.java
@FacesComponent("childComp")
public class ChildComponent extends UINamingContainer {
public void childAction() {
}
}
TestModel.java
@RequestScoped
@Named
public class TestModel {
private TreeModel treeModel;
public TestModel() {
this.treeModel = new ListTreeModel();
this.treeModel.addChild("1").addChild("1.1");
this.treeModel.addChild("2").addChild("2.2");
}
public TreeModel getTreeModel() {
return treeModel;
}
}
示例中复合组件中使用了o:tree,子组件的#{cc}解析错误,点击link会得到一个像这样的异常:
Caused by: javax.el.MethodNotFoundException: /resources/test/childComp.xhtml @10,71 action="#{cc.childAction}": Method not found: ParentComponent@422dcfd4.childAction()
如果 o:tree 没有像第二个示例那样嵌套在复合组件中,命令 link 将按预期工作。
这是 Omnifaces 中的错误吗?我是不是做错了什么?
这确实是 OmniFaces 中的一个错误。我在 this commit 中修复了它,修复程序在今天的 2.3 快照中可用(2.3 最终版本预计在本周结束,所以你很准时)。
原因是,排队的动作事件基本上是 caught and wrapped by <o:tree>
以便它可以记住当前迭代的树节点,它被触发。但是,在广播动作事件时,它是在 <o:tree>
本身上调用的,而不是在源组件(您的命令 link)上调用的。因此,只有 <o:tree>
上下文中的 #{cc}
本身才被视为复合组件父级。
我通过 pushing 将源组件自己的复合组件父级(如果有)修复到 EL 上下文中。
Original Tree#broadcast()
method:
wrapped.getComponent().broadcast(wrapped);
Fixed Tree#broadcast()
method:
UIComponent source = wrapped.getComponent();
pushComponentToEL(context, getCompositeComponentParent(source));
try {
source.broadcast(wrapped);
}
finally {
popComponentFromEL(context);
}
感谢您的举报!