Most of my page navigation uses get requests and now I have a form where the parameters should be included as query-string parameters using f:param
inside h:commandButton
or checking attributes for includeViewParams
to use UIViewParameter
.
I do not want to use includeViewParams
since this would include all view defined parameters, I just want to use the ones provided as child's of the command component.
<h:form>
<p:inputText value="#{bean.value1}"/>
<p:selectOneMenu value="#{bean.value2}"/>
<p:commandButton action="#{utilBean.performActionParams(outcome)}">
<f:param name="key1" value="#{bean.value1}"/>
<o:param name="key1" value="#{bean.value2}" converter="#{bean.converter}/>
</p:commandButton>
</h:form>
public String performActionParams(final String outcome)
{
final UriBuilder uriBuilder = UriBuilder.fromPath(outcome);
final FacesContext context = FacesContext.getCurrentInstance();
final UIComponent component = UIComponent.getCurrentComponent(context);
for (final UIComponent child : component.getChildren())
if (child instanceof UIParameter)
{
final UIParameter param = (UIParameter) child;
if (!param.isDisable() && !StringUtils.isBlank(param.getName()))
{
final Object value = param.getValue();
if (value != null)
uriBuilder.queryParam(param.getName(), value);
}
}
return uriBuilder.build().toString();
}
This logic is not really complicated but it seems so redundant since it seems to be the same logic as in h:link
and h:button
.
So does someone knows where this logic is implemented?
In Mojarra, this kind of logic is also buried in OutcomeTargetRenderer#getEncodedTargetURL()
(and in HtmlBasicRenderer#getParamList()
). The only public part which is provided by the API is the ViewHandler#getBookmarkableURL()
, however it takes a Map
as parameter map, not a list of UIParameter
components.
I'm not sure what the concrete functional requirement is, but so far it seems that you actually want to fire a simple GET request and not a POST request. In that case, you should be using <h:link>
or <h:button>
(or <p:button>
). Their renderers extend from OutcomeTargetRenderer
having this logic internally implemented. You can just use EL in outcome
attribute (the probable assumption that this is not possible was perhaps your reason why you tried a command button).
<p:button outcome="#{outcome}">
<f:param name="key1" value="#{value1}" />
<o:param name="key1" value="#{value2}" converter="#{bean.converter}" />
</p:button>
Update: as per the comments, the concrete functional requirement is basically to turn a JSF POST form along with the submitted data into a GET request. In that case, it'd be easier if you bind the inputs to a Map
which is ready for use in getBookmarkableURL()
.
<h:inputText value="#{bean.params.key1}" />
<h:inputText value="#{bean.params.key2}" />
<p:commandButton value="#{bean.submit(outcome)}" />
with
private Map<String, String> params;
@PostConstruct
public void init() {
params = new HashMap<>();
}
public String submit(outcome) {
// ...
return context.getApplication().getViewHandler()
.getBookmarkableURL(context, outcome, params, false);
// TODO: Is faces-redirect=true also considered?
}