JSF 组件的“ValueExpression Map”

问题描述 投票:0回答:3

我使用 f:attribute 标记将值表达式存储在 JSF 组件中,例如:

<h:inputText ...>
  <f:attribute name="myId1" value="#{bean.prop1}" />
  <f:attribute name="myId2" value="#{bean.prop2}" />
  <f:attribute name="myId3" value="#{bean.prop3}" />
</h:inputText>

有没有办法以编程方式访问所有这些值表达式? (不知道名称 myId1、myId2...)

JSF 2.1 规范的第 9.4.2 节规定这些值存储在“组件的 ValueExpression Map 中”。 这是完整规范中唯一出现的术语“ValueExpression Map”。 我如何访问该地图?

Jboss/Mojarra 实现的 UI 组件方法 getValueExpression() 中的地图

getStateHelper().get(UIComponentBase.PropertyKeys.bindings) 

用于获取值表达式。

我猜该映射是“ValueExpression Map”的超集? 我能否确定所有实现和所有继承的(标准)组件都使用该映射来存储 ValueExpressions?

谢谢。

jsf
3个回答
2
投票

理论上你应该能够通过

UIComponent#getAttributes()
:

看到它们全部
var attributes = component.getAttributes();

for (var entry : attributes.entrySet()) {
    System.out.printf("name=%s, value=%s%n", entry.getKey(), entry.getValue());
}

但是,这并不像您期望的那样工作。它只返回静态属性。这似乎永远不会被修复/实施。另请参阅Mojarra 问题 640。不过,我确实同意 javadoc 需要进一步澄清。

我建议坚持使用预定义前缀和增量数字后缀的属性,就像您在示例中所示的那样。您可以按照以下方式收集它们:

var attributes = component.getAttributes();
var values = new ArrayList<Object>();

for (int i = 1; i < Integer.MAX_VALUE; i++) {
    var name = "myId" + i;
    var value = attributes.get(name);
    if (value == null && component.getValueExpression(name) == null) break;
    values.add(value);
}

System.out.println(values);

1
投票

BalusC 给出的答案的替代方案可能是使用嵌套构面或 UIParameter 组件。可以使用 getFacets 将分面作为映射进行检索,但您可能需要在每个分面内放置一个额外的 UIOutput 来访问其值表达式。

嵌套的

UIParameters 可以通过迭代子组件并检查 instanceof UIParameter

 来访问。 UIParameters 具有 
name
value
 属性,因此可以轻松转换为地图。

我在自定义组件中使用了参数,但我不确定示例中的标准 UIInput 对这些参数有何反应。


0
投票
BalusC 是对的。 UIComponent#getAttributes().get(name) 从两个地方获取值 - 首先从属性映射中获取值,然后如果没有找到则从“值表达式映射”中获取值。要输入一些值,您必须调用 UIComponent#setValueExpression(name, ValueExpression)。如果 value 是文字,则将其存储到属性映射中,否则存储到“值表达式映射”中。那么一切就都OK了。

© www.soinside.com 2019 - 2024. All rights reserved.