Best way to “switch” bean on selection in JSF

允我心安 提交于 2020-01-07 05:46:08

问题


I have a bean "Player" When I select a value in the selectOneMenu I would like to "switch" to the bean that's matching in the database.

I have the beans sent back to the select one menu in

public List<Player> getAllPlayers() { }

Updated the dropdown to this.

<h:selectOneMenu value="#{servicePlayer.myPlayer.combinedName}"
    converter="playerConverter" id="playerList">
    <f:selectItems value="#{servicePlayer.allPlayers}" var="player"
        itemLabel="#{player.combinedName}" itemValue="#{player.id}" />
</h:selectOneMenu>

But I still can't get it to send the ID to the converter. It will send in the firstName from the player.

@FacesConverter(value = "playerConverter")
public class PlayerConverter implements Converter {

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        if (value == null) {
            return null;
        }

        long idValue;
        try {
            idValue = Long.parseLong(value);
        }
        catch (NumberFormatException ex)
        {
            return null;
        }

        ServicePlayer servicePlayer = context.getApplication()
                .evaluateExpressionGet(context, "#{servicePlayer}",
                        ServicePlayer.class);
        Player player = servicePlayer.getPlayerByID(idValue);
        return player;

    }

    @Override
    public String getAsString(FacesContext arg0, UIComponent arg1, Object value) {
        String string = null;
        if (value instanceof Player) {
            string = ((Player) value).getFirstName();
        }
        return string;
    }

}

public class ServicePlayer {

    private static final String PERSISTENCE_UNIT_NAME = "BowlingFacelets";
    public static EntityManagerFactory factory;
    Player myPlayer;

    public Player getMyPlayer() {
        return myPlayer;
    }


    public void setMyPlayer(Player myPlayer) {
        this.myPlayer = myPlayer;
    }


    public List<Player> getAllPlayers() {

        if (factory == null) {
            factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
        }

        EntityManager em = factory.createEntityManager();
        //Order by the matchdate.
        //Query q = em.createQuery("select t from DBTest t");
        Query q = em.createQuery("select t from Player t");

        List<Player> players = q.getResultList();
        for (Player aPlayer : players) {
          System.out.println(aPlayer);
        }
        System.out.println("Size: " + players.size());

        em.close();

        return players;
    }


public Player getPlayerByID(long id) {

        if (factory == null) {
            factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
        }

        EntityManager em = factory.createEntityManager();
        //Query q = em.createQuery("select t from Player t where t.name = '" + playerName + "'");
        //List<Player> players = q.getResultList();
        Player currentPlayer = em.find(Player.class, id);

        return currentPlayer;

    }


}

回答1:


A JSF Converter does the job of converting an Object to the string value for the itemValue attribute and then recover that Object from the string value. For your case, the Object is the Player entity while the value is the String representation of its id (could be anything else, as long as you know it's unique).

Basically, using this converter:

@FacesConverter(value = "playerConverter")
public class PlayerConverter implements Converter {

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        if (value == null) {
            return null;
        }

        long idValue;
        try {
            idValue = Long.parseLong(value);
        }
        catch (NumberFormatException ex)
        {
            return null;
        }

        ServicePlayer servicePlayer = context.getApplication()
                .evaluateExpressionGet(context, "#{servicePlayer}",
                        ServicePlayer.class);
        Player player = servicePlayer.getPlayerByID(idValue);
        return player;

    }

    @Override
    public String getAsString(FacesContext arg0, UIComponent arg1, Object value) {
        String string = null;
        if (value instanceof Player) {
            string = ((Player) value).getId();
        }
        return string;
    }

}

Note I changed the name you're returning by the id. That way, being the player id 1, JSF knows the String value for that is "1". That's the value for the selection, which is obtained by the getAsString method.

When you POST the form, JSF has to recover the Player entity from the "1" value, so you use Converter's getAsObject to load it from the DB.

That way it would be enough to reference the object itself from the view to let jsf do the conversion:

<h:selectOneMenu value="#{servicePlayer.myPlayer.combinedName}"
    converter="playerConverter" id="playerList">
    <f:selectItems value="#{servicePlayer.allPlayers}" var="player"
        itemLabel="#{player.combinedName}" itemValue="#{player}" />
</h:selectOneMenu>



回答2:


I think you've misunderstood what the value attribute of the selectOneMenu refers to. It's use is like in all other input components the place to store the user input (or where to take an existing value from).

Check http://www.jsftoolbox.com/documentation/help/12-TagReference/core/f_selectItems.html. You will need to set key and value pairs based on a 'var' attribute on the f:select items, else JSF has no real way of knowing what you want to do with the Player object.

So given that key/value pairs (key goes into whatever you sets as the value attribute and value is shown to the user) is in place, and if you for example use the player.id as the value, you can fetch a user based on that id.



来源:https://stackoverflow.com/questions/20629975/best-way-to-switch-bean-on-selection-in-jsf

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!