0

Primefaces code is lengthy and it may be hard to keep the oversight in a big web application.

Some example:

HTML

<p:selectOneMenu id="clientToCopyRoles" value="#{form.clientToCopyRoles}"
        rendered="#{form.copyAllowed}">
    <f:selectItem value="#{null}" itemLabel="#{msg.clientSelect}"/>
    <f:selectItems value="#{form.possibleClientsForCopying}"/>
</p:selectOneMenu>
<p:commandButton id="copyRolesToClient"
        rendered="#{form.copyAllowed}"
        disabled="#{form.canCopyRoles}"
        action="#{form.copyRolesToClient()}"
        value="#{msg.copyToClient}"/>

Required Java

private boolean copyAllowed;
private Client clientToCopyRoles;
private List<SelectItem> possibleClientsForCopying;
private boolean canCopyRoles;

public Client getClientToCopyRoles() {
    return clientToCopyRoles;
}

public void setClientToCopyRoles(Client clientToCopyRoles) {
    this.clientToCopyRoles = clientToCopyRoles;
}

public boolean isCopyAllowed() {
    return copyAllowed;
}

public void copyRolesToClient() {
    businessLogic.copyRolesToClient(clientToCopyRoles);
}

public List<SelectItem> getPossibleClientsForCopying() {
    return possibleClientsForCopying;
}

public boolean isCanCopyRoles() {
    return canCopyRoles;
}

This is long, there is no obvious relationship between the class fields and the components in HTML, and it misleads programmers to implement complicated and slow logic in the getters which, as we know, need to be invoked several times by JSF during processing, and must never throw any exceptions. What I would want is something like this:

HTML

<p:selectOneMenu id="clientToCopyRoles" java="#{form.clientToCopyRoles}"
                 nullItemLabel="#{msg.clientSelect}" />
<p:commandButton id="copyRolesToClient" java="#{form.copyRolesToClient}"
                 value="#{msg.copyToClient}"/>

Required Java

private final SelectOneMenu<Client> clientToCopyRoles = new SelectOneMenu<>();
private final CommandButton copyRolesToClient = new CommandButton();

public Form() {
    clientToCopyRoles.setRendered(true);
    clientToCopyRoles.setNullItemSelctable(true);
    clientToCopyRoles.setItems(possibleClientsForCopying, Client::getName);
    clientToCopyRoles.onChange(selectOneMenu ->
            copyRolesToClient.setDisabled(selectOneMenu.getSelectedItem() != null));

    copyRolesToClient.setRendered(true);
    copyRolesToClient.setDisabled(true);
    copyRolesToClient.onClick(commandButton ->
            businessLogic.copyRolesToClient(clientToCopyRoles.getSelectedItem()));
}

public SelectOneMenu<Client> getClientToCopyRoles() {
    return clientToCopyRoles;
}

public CommandButton copyRolesToClient() {
    return copyRolesToClient;
}

Of course, I could write such classes as SelectOneMenu and CommandButton, but it would still leave me with much more of HTML:

<p:selectOneMenu id="clientToCopyRoles" value="#{form.clientToCopyRoles.selectedItem}"
        rendered="#{form.clientToCopyRoles.rendered}">
    <f:selectItem value="#{null}" itemLabel="#{msg.clientSelect}"/>
    <f:selectItems value="#{form.clientToCopyRoles.items}"/>
</p:selectOneMenu>
<p:commandButton id="copyRolesToClient"
        rendered="#{form.copyRolesToClient.rendered}"
        disabled="#{form.copyRolesToClient.disabled}"
        action="#{form.copyRolesToClient.click()}"
        value="#{msg.copyToClient}"/>

And if I forget to explicitly assign an attribute like rendered in the HTML, I could set it to true or false on my bean and nothing would happen.

It feels to me like this is something so basic that it should definitely (and I assume, it is) somewhere in the Primefaces classes, and I was just unable to find or understand it correctly. I took a close look at the package javax.faces.component, which is what the Primefaces’ components’ binding attribute expect, where I assumed to find it. There are some things related, there is something like UISelectMany and UISelectItems, but it does not look like a clean and easy-to-use API to be used for programming the front-end, but for doing the internals (HTML, AJAX, etc.).

Are there such kind of back-end classes for the Primefaces components, either official part of, or maybe is there a project around which deals with just this (at least the Java part, perhaps)? I would like to introduce the default instead of writing my own, if possible.

Kukeltje
  • 12,223
  • 4
  • 24
  • 47
Matthias Ronge
  • 9,403
  • 7
  • 47
  • 63
  • There are such classes you probably found already: `org.primefaces.component.commandbutton.CommandButton`, `org.primefaces.component.selectonemenu.SelectOneMenu`. You can use the binding attribute to get their instances but this [is discouraged](https://stackoverflow.com/a/14917453/865107). The state you push to these instances is not view scoped and therefore forgotton before subsequent AJAX actions are performed, leading to unexpected results. – Selaron Nov 06 '19 at 08:49
  • Possibly [DynaForm](//www.primefaces.org/showcase-ext/views/dynaForm.jsf) from PrimeFaces Extensions is a thing? – Selaron Nov 06 '19 at 08:50
  • 2
    Just refactor duplication into tagfiles or perhaps composites. This is not PrimeFaces related. Just standard JSF. – BalusC Nov 06 '19 at 14:14
  • BalusC is right and effectively you'd have a similar problem with other web frameworks, unless you also create things similar to tag files. – Kukeltje Nov 06 '19 at 19:05

0 Answers0