当前位置: 首页 > 知识库问答 >
问题:

PrimeFaces SelectOneMenu转换器中断组件

赵选
2023-03-14

给定组件:https://www.primefaces.org/showcase/ui/input/oneMenu.xhtml

我的测试的完整来源是:https://github.com/dannymk/PrimefacesTest

无法使用转换器使组件与对象一起工作。不知道如何解决这个问题。

package org.primefaces.test;

import java.io.Serializable;

public class Player implements Serializable {

    private Integer id;
    private String name;
    
    Player(Integer id, String name){
        this.id = id;
        this.name = name;
    }
    
    /**
     * @return the id
     */
    public Integer getId() {
        return id;
    }

    /**
     * @param id the id to set
     */
    public void setId(Integer id) {
        this.id = id;
    }

    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

}
package org.primefaces.test;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author Daniel Maldonado
 */
public class PlayerService implements Serializable{

    private List<Player> available = new ArrayList<>();
    
    public PlayerService() {
        available.add(new Player(1, "One"));
        available.add(new Player(2, "Two"));
        available.add(new Player(3, "Three"));
        available.add(new Player(4, "Four"));
        available.add(new Player(5, "Five"));
        
    }

    /**
     * @return the available
     */
    public List<Player> getAvailable() {
        return available;
    }

    /**
     * @param available the available to set
     */
    public void setAvailable(List<Player> available) {
        this.available = available;
    }
    
    
}
java prettyprint-override">package org.primefaces.test;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;
import javax.inject.Inject;
import javax.inject.Named;

/**
 *
 * @author Daniel Maldonado
 */
@Named
@FacesConverter(value = "playerConverter", managed = true)
public class PlayerConverter implements Converter<Player> {
    
   @Inject
   PlayerService service;
   
   @Override
   public Player getAsObject(FacesContext context, UIComponent component, String value) {
      if (value != null && value.trim().length() > 0) {
         Player found = service.getAvailable().stream()
            .filter(player -> player.getName().equals(value))
            .findAny()
            .orElse(null);

         return found;
      }
      return null;
      
   }

   @Override
   public String getAsString(FacesContext context, UIComponent component, Player o) {
      if (o != null){
         return o.getName();
        }
      return null;
      
   }    

}
package org.primefaces.test;

import java.io.Serializable;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Inject;
import javax.inject.Named;

import lombok.Data;

@Data
@Named
@ViewScoped
public class TestView implements Serializable {
    
    private String hello;
     
     private List<Player> available;
     private Player selected;
     
     @Inject
     PlayerService service;
    
    @PostConstruct  
    public void init() {
        setHello("Welcome to PrimeFaces!!!");
        this.available = service.getAvailable();
          
    }

    /**
     * @return the available
     */
    public List<Player> getAvailable() {
        return available;
    }

    /**
     * @param available the available to set
     */
    public void setAvailable(List<Player> available) {
        this.available = available;
    }

    /**
     * @return the selected
     */
    public Player getSelected() {
        return selected;
    }

    /**
     * @param selected the selected to set
     */
    public void setSelected(Player selected) {
        this.selected = selected;
    }

    /**
     * @return the hello
     */
    public String getHello() {
        return hello;
    }

    /**
     * @param hello the hello to set
     */
    public void setHello(String hello) {
        this.hello = hello;
    }

}
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:f="http://xmlns.jcp.org/jsf/core"
      xmlns:p="http://primefaces.org/ui"
      xmlns:h="http://xmlns.jcp.org/jsf/html">

    <h:head>
        <title>PrimeFaces Test - SelectOneMenu</title>
        <h:outputScript name="test.js" />
    </h:head>
    <h:body>

        <h1>#{testView.hello}</h1>
        <h:form id="frmTest">

            <p:panelGrid id="playerPanel" columns="2">
                <p:outputLabel value="Selected player: #{testView.selected.name}" />
                
                <p:selectOneMenu id="playerContainer" value="#{testView.selected}" var="p" converter="playerConverter" >
                    <f:selectItem itemLabel="Select One" itemValue="" />
                    <f:selectItems value="#{testView.available}" var="actual" itemLabel="#{actual.name}" itemValue="#{actual}" />
                    <p:column>
                            #{p.name}
                    </p:column>
                    <p:ajax event="valueChange" update="playerPanel" />
                </p:selectOneMenu>            

            </p:panelGrid>
            

        </h:form>

    </h:body>
</html>

我会出现以下错误:

java.lang.ClassCastException: java.lang.String cannot be cast to org.primefaces.test.Player
        at org.primefaces.test.PlayerConverter.getAsString(PlayerConverter.java:38)

我改变什么似乎无关紧要,相信我,我已经尝试了很多转换器的实现,并且在视图中使用了“#{palyerConverter}”而不是“playerConverter”,但仍然无法使其工作。


共有2个答案

唐元青
2023-03-14

多亏了@Jasper de Vries,最后只做了几处改动就成功了:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:f="http://xmlns.jcp.org/jsf/core"
      xmlns:p="http://primefaces.org/ui"
      xmlns:h="http://xmlns.jcp.org/jsf/html">

    <h:head>
        <title>PrimeFaces Test - SelectOneMenu</title>
        <h:outputScript name="test.js" />
    </h:head>
    <h:body>

        <h1>#{testView.hello}</h1>
        <h:form id="frmTest">

            <p:panelGrid id="playerPanel" columns="2">
                <p:outputLabel value="Selected player: #{testView.selected.name}" />
                <p:selectOneMenu id="playerContainer" value="#{testView.selected}" var="p" converter="playerConverter">
                    <f:selectItems value="#{testView.available}" var="actual" itemLabel="#{actual.name}" itemValue="#{actual}" />
                    <p:column>
                        #{p.name}
                    </p:column>
                    <p:ajax event="valueChange" update="playerPanel" />
                </p:selectOneMenu>

            </p:panelGrid>
            

        </h:form>

    </h:body>
</html>

并且特别不要忘记在“列出”的Object中实现EQUALS方法:

package org.primefaces.test;

import java.io.Serializable;
import java.util.Objects;

public class Player implements Serializable {

    private Integer id;
    private String name;
    
    Player(Integer id, String name){
        this.id = id;
        this.name = name;
    }
    
   @Override
   public boolean equals(Object obj) {
          if(obj == null)
                  return false;

          if(!(obj instanceof Player))
                  return false;

          Player compare = (Player) obj;

          return Objects.equals(compare.getId(), this.getId());
   }

   @Override
   public int hashCode() {
          int hash = 1;
      return hash * 31 + this.getName().hashCode();
   }    
    
    /**
     * @return the id
     */
    public Integer getId() {
        return id;
    }

    /**
     * @param id the id to set
     */
    public void setId(Integer id) {
        this.id = id;
    }

    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

}
佟云
2023-03-14

你的问题在这一行:

html prettyprint-override"><f:selectItem itemLabel="Select One" itemValue="" />

当前,您正在传递一个空字符串作为项值,这是您的转换器所不期望的。可以使用itemValue=“#{null}”或从no-select选项中完全删除itemValue。

另见:

  • 在JSF中向selectOneMenu添加“无选择”选项的最佳方式

 类似资料:
  • 问题内容: 如果我有带签名的元组,则无法将其强制转换为。编译器说: 错误:无法表示元组转换((String,Bool)’到’(String,Any)’ 但这应该可行,因为可以安全地使用它。如果执行类似的操作,几乎会引发相同的错误: 错误: 无法将类型’(Swift.String,Swift.Bool)’的值强制转换为’(protocol <>,protocol <>)) 那么,有什么变通办法,尤其

  • 问题内容: 是否有一种优雅的方法将原语数组转换为相应容器对象的数组- 例如,将a 转换为a ?还是我坚持循环浏览并手动执行? 是的,循环并不完全困难。有点丑。 问题答案: Apache Commons Apache Commons / Lang 有一个ArrayUtils类,用于定义这些方法。 所有称为 从原始数组转换为包装器数组的方法 从包装对象数组到原始数组的所有转换 例: 番石榴 但是然后我

  • 我有一个与PHP链接的JavaScript AJAX。PHP有以下代码: 它的输出将是一个字符串: 我想用这些元素创建一个JavaScript数组: 是否有预定义的函数要使用?你有解决办法吗?

  • 我想将web设计师用纯HTML编写的复杂div容器转换为React组件。此div容器具有React to manage的状态。我知道我可以将div转换为JSX,但这意味着设计师和我都要加倍努力。危险的是,Html不处理状态。我可以创建React的子类。组件,定义状态并在不使用JSX的情况下将状态值呈现到div容器中? 下面是div容器标记的一个片段:

  • 如果您需要在Aurelia应用程序中转换某些值,则可以使用converters而不是手动将值转换为所需的格式。 转换日期 当我们想要将默认日期值转换为某种特定格式时,我们可以使用momentJS库。 这是一个用于操作日期的小型库。 C:\Users\username\Desktop\aureliaApp>jspm install moment 让我们创建一个新文件converters.js 。

  • XStream转换器是XStream库的关键组件,它负责将对象转换为XML,反之亦然。 XStream为常见类型提供了大量转换器,例如基元,字符串,文件,集合,数组和日期。 使用转换器 让我们使用SingleValueConvertor,其目的是将对象转换为单个字符串。 我们将使用SingleValueConvertor将对象写为属性字符串。 创建转换器 class NameConverter i