子项的 JSF 自定义组件请求映射值 null
JSF custom component requestmap value null for children
我创建了一个组件,用于访问基于数字转换为另一种类型的通用对象。我在请求映射中使用 "var" 属性以允许我的组件中的子级访问该对象。尝试在子组件中访问由 "var" 命名的对象时,出现以下异常:
javax.el.PropertyNotFoundException:目标无法到达,标识符 'objectName' 解析为空。
这是我的组件代码和标记:
@FacesComponent(value = "components.AgendaItemTextAccessor", createTag = true)
public class AgendaItemTextAccessor extends UIComponentBase{
public String getVar(){
return (String) getStateHelper().eval("var");
}
public void setVar(String var){
getStateHelper().put("var", var);
}
public AgendaItemText getValue(){
return (AgendaItemText) getStateHelper().eval("value");
}
public void setValue(AgendaItemObject text){
getStateHelper().put("value", text);
}
@Override
public boolean getRendersChildren() {
return true;
}
@Override
public void encodeChildren(FacesContext context) throws IOException{
if ((context == null)){
throw new NullPointerException();
}
AgendaItemText text = (AgendaItemText)getValue();
String varname = getVar();
Map<String, Object> requestMap = context.getExternalContext().getRequestMap();
Object varStore = requestMap.get(varname); // in case this Object already exists in the requestMap,
// emulate "scoped behavior" by storing the value and
// restoring it after all rendering is done.
if(text != null){
requestMap.put(varname, text);
for(UIComponent child: getChildren()){
child.encodeAll(context);
}
// restore the original value
if(varStore != null){
requestMap.put(varname, varStore);
}else{
requestMap.remove(varname);
}
}
}
@Override
public String getFamily() {
return "components.AgendaItemTextAccessor";
}
标记
<xx:agendaItemTextAccessor value="#{itemValue}" var="itemVar">
<p:inputText value="#{itemVar.text}">
<p:ajax event="blur" listener="#{Controller.printMe(itemVar)}" />
</p:inputText>
</xx:agendaItemTextAccessor>
We were instructed to create a component that takes in the abstract object and cast it base on a field that defines its type
您在实现功能需求方面走错了方向。 var
增加了不必要的复杂性。直接用#{itemValue}
就可以了。在 EL 中,无论如何,一切都是 Object
(反射,你知道的),所以绝对不需要在将它放回 EL 之前向上、向下、向左或向右投射。
<p:inputText value="#{itemValue.text}">
<p:ajax event="blur" listener="#{controller.printMe(itemValue)}" />
</p:inputText>
至于具体的问题,你遇到它是因为你只在encodeChildren()
期间设置它而不是在processDecodes()
、processValidators()
、processUpdates()
和[=18=期间设置它].换句话说,它只在渲染响应阶段可用,而不是在它可能相关的所有其他阶段。不幸的是,您没有在任何地方显示完整的堆栈跟踪,但它应该指出哪个阶段有问题(我的有根据的猜测是 processValidators()
)。通常,var
仅在转发器或仅输出组件中实现。查看 source code of <ui:repeat>
how to do it right (and peek in source code of <o:tree>
如何以 DRY 方式进行操作)。
我创建了一个组件,用于访问基于数字转换为另一种类型的通用对象。我在请求映射中使用 "var" 属性以允许我的组件中的子级访问该对象。尝试在子组件中访问由 "var" 命名的对象时,出现以下异常: javax.el.PropertyNotFoundException:目标无法到达,标识符 'objectName' 解析为空。
这是我的组件代码和标记:
@FacesComponent(value = "components.AgendaItemTextAccessor", createTag = true)
public class AgendaItemTextAccessor extends UIComponentBase{
public String getVar(){
return (String) getStateHelper().eval("var");
}
public void setVar(String var){
getStateHelper().put("var", var);
}
public AgendaItemText getValue(){
return (AgendaItemText) getStateHelper().eval("value");
}
public void setValue(AgendaItemObject text){
getStateHelper().put("value", text);
}
@Override
public boolean getRendersChildren() {
return true;
}
@Override
public void encodeChildren(FacesContext context) throws IOException{
if ((context == null)){
throw new NullPointerException();
}
AgendaItemText text = (AgendaItemText)getValue();
String varname = getVar();
Map<String, Object> requestMap = context.getExternalContext().getRequestMap();
Object varStore = requestMap.get(varname); // in case this Object already exists in the requestMap,
// emulate "scoped behavior" by storing the value and
// restoring it after all rendering is done.
if(text != null){
requestMap.put(varname, text);
for(UIComponent child: getChildren()){
child.encodeAll(context);
}
// restore the original value
if(varStore != null){
requestMap.put(varname, varStore);
}else{
requestMap.remove(varname);
}
}
}
@Override
public String getFamily() {
return "components.AgendaItemTextAccessor";
}
标记
<xx:agendaItemTextAccessor value="#{itemValue}" var="itemVar">
<p:inputText value="#{itemVar.text}">
<p:ajax event="blur" listener="#{Controller.printMe(itemVar)}" />
</p:inputText>
</xx:agendaItemTextAccessor>
We were instructed to create a component that takes in the abstract object and cast it base on a field that defines its type
您在实现功能需求方面走错了方向。 var
增加了不必要的复杂性。直接用#{itemValue}
就可以了。在 EL 中,无论如何,一切都是 Object
(反射,你知道的),所以绝对不需要在将它放回 EL 之前向上、向下、向左或向右投射。
<p:inputText value="#{itemValue.text}">
<p:ajax event="blur" listener="#{controller.printMe(itemValue)}" />
</p:inputText>
至于具体的问题,你遇到它是因为你只在encodeChildren()
期间设置它而不是在processDecodes()
、processValidators()
、processUpdates()
和[=18=期间设置它].换句话说,它只在渲染响应阶段可用,而不是在它可能相关的所有其他阶段。不幸的是,您没有在任何地方显示完整的堆栈跟踪,但它应该指出哪个阶段有问题(我的有根据的猜测是 processValidators()
)。通常,var
仅在转发器或仅输出组件中实现。查看 source code of <ui:repeat>
how to do it right (and peek in source code of <o:tree>
如何以 DRY 方式进行操作)。