selectonemenu,当editable = false时,无法提交表单

时间:2015-06-11 18:00:21

标签: jsf primefaces

如果editable设置为true,那么我的表单正在运行,但是当它被设置为false时我的表单正在运行。如果为false,则甚至不调用提交操作方法。我需要它是假的(不可编辑,所以我可以在db中存储正确的值)。

这是我添加的菜单。

<tr><td>
<h:outputLabel for="country">#{registering.Country}: </h:outputLabel></td>
    <td><p:selectOneMenu editable="false" id="country" required="true" requiredMessage="Required" value="#{subscribeUser.user.countryBean}" converter="#{countriesConverter}" effect="fold" >
        <f:selectItem itemValue="#{null}" itemLabel="#{registering.SelectCountry}" />
        <f:selectItems value="#{countriesConverter.countries}" var="country" itemLabel="#{country.shortName}" itemValue="#{country}" />
    </p:selectOneMenu></td><td></td><td>
<span class="error"><h:message id="countryMessage" for="country"/></span></td>
</tr> 

请注意,选择一个菜单有editable =&#34; false&#34;在那种情况下它不起作用。但如果我把editable =&#34; true&#34;它有效。

这里是完整的表格,最后2个字段有问题:

<h:form>

   <table class="registration">             

        <!-- username -->
        <tr><td>
        <h:outputLabel for="username">#{registering.Username}: </h:outputLabel></td><td>
        <p:inputText id="username" value="#{subscribeUser.user.username}" 
            validator="#{usernameValidator.validate}" maxlength="#{values.small}">
            <f:passThroughAttribute name="required" value="true"/>
            <f:ajax event="blur" render="usernameCheck usernameMessage submit"></f:ajax>
        </p:inputText></td><td>
        <h:panelGroup id="usernameCheck">
            <h:graphicImage library="images/icons" name="failed_indicator.png" rendered="#{usernameValidator.isIndicatorVisible.usernameFailed}"></h:graphicImage>
            <h:graphicImage library="images/icons" name="success_indicator.png" rendered="#{usernameValidator.isIndicatorVisible.usernameSuccess}"></h:graphicImage>
        </h:panelGroup></td><td>
        <span class="error"><h:message id="usernameMessage" for="username"/></span></td>
        </tr>

        <!-- password -->           

        <tr><td>
        <h:outputLabel for="password">#{registering.Password}: </h:outputLabel></td><td>
        <p:password id="password" value="#{subscribeUser.userCredential.password}" feedback="true"

            promptLabel="#{registering.PleaseEnterPass}" weakLabel="#{registering.Weak}"
            goodLabel="#{registering.Good}" strongLabel="#{registering.Strong}"
            requiredMessage="#{registering.reqPassword}"
            validator="#{passwordValidator.validate}">
            <f:passThroughAttribute name="required" value="true"/>
            <f:attribute name="confirm" value="#{confirmPassword}" />
            <f:passThroughAttribute name="required" value="true"/>
            <f:ajax event="blur" execute="password confirmPassword" render="passwordMessage passwordCheck confpasswordCheck submit"></f:ajax>                       
        </p:password></td><td>
        <h:panelGroup id="passwordCheck">
            <h:graphicImage library="images/icons" name="failed_indicator.png" rendered="#{passwordValidator.isIndicatorVisible.passwordFailed}"></h:graphicImage>
            <h:graphicImage library="images/icons" name="success_indicator.png" rendered="#{passwordValidator.isIndicatorVisible.passwordSuccess}"></h:graphicImage>
        </h:panelGroup>
        </td><td>
        <span class="error"><h:message id="passwordMessage" for="password"/></span></td>
        </tr>           

        <!-- Confirm password -->

        <tr><td>
        <h:outputLabel for="confirmPassword" value="#{registering.ConfirmPass}: "/></td><td>
        <p:password id="confirmPassword" required="true"
            requiredMessage="#{registering.PleaseConfirmPassword}" 
            binding="#{confirmPassword}">
            <f:passThroughAttribute name="required" value="true"/>
            <f:ajax event="blur" execute="password confirmPassword" render="passwordMessage passwordCheck confpasswordCheck submit"></f:ajax>

            </p:password> </td><td>
            <h:panelGroup id="confpasswordCheck">
                <h:graphicImage library="images/icons" name="failed_indicator.png" rendered="#{passwordValidator.isIndicatorVisible.passwordFailed}"></h:graphicImage>
                <h:graphicImage library="images/icons" name="success_indicator.png" rendered="#{passwordValidator.isIndicatorVisible.passwordSuccess}"></h:graphicImage>
            </h:panelGroup>

            </td><td>
        <span class="error"><h:message id="passwordConfMessage" for="confirmPassword" /></span></td>
        </tr>

        <!-- Email -->

        <tr><td>
        <h:outputLabel for="email">#{registering.Email}: </h:outputLabel></td><td>
        <p:inputText id="email" required="true" value="#{subscribeUser.user.email}" 
            validator="#{emailValidator.validate}"
            requiredMessage="#{registering.reqEmail}">
            <f:passThroughAttribute name="required" value="true"/>
            <f:passThroughAttribute name="type" value="email"/>
            <f:passThroughAttribute name="maxlength" value="100"/>
            <f:ajax event="blur" render="emailCheck emailMessage submit"></f:ajax>

        </p:inputText></td><td>
         <h:panelGroup id="emailCheck">
            <h:graphicImage library="images/icons" name="failed_indicator.png" rendered="#{emailValidator.isIndicatorVisible.emailFailed}"></h:graphicImage>
            <h:graphicImage library="images/icons" name="success_indicator.png" rendered="#{emailValidator.isIndicatorVisible.emailSuccess}"></h:graphicImage>
        </h:panelGroup> </td><td>
        <span class="error"><h:message id="emailMessage" for="email"/></span></td>
        </tr>

        <!-- Country -->

            <tr><td>
        <h:outputLabel for="country">#{registering.Country}: </h:outputLabel></td>
        <td colspan="3"><p:selectOneMenu required="true" editable="true" id="country" value="#{subscribeUser.user.countryBean}" converter="#{countriesConverter}" effect="fold">
                <f:selectItems value="#{countriesConverter.countries}" var="country" itemLabel="#{country.shortName}" itemValue="#{country}" />
            </p:selectOneMenu></td>
        </tr>   
        <!-- Timezone -->   

         <tr><td>
        <h:outputLabel for="timezone">#{registering.Timezone}: </h:outputLabel></td>
        <td colspan="3">
            <p:selectOneMenu id="timezone" editable="true" required="true" value="#{subscribeUser.user.timezoneOffset}" converter="#{timezonesConverter}" effect="fold" >
                <f:selectItems value="#{timezonesConverter.timezonesList}" var="timezone" itemLabel="#{timezone.name}" itemValue="#{timezone}"  />

            </p:selectOneMenu></td>
        </tr>  



    </table>
    <div class="areYouARobot" ><div class="captchaLabel">#{registering.AreYouARobot}</div>
    <!-- <div class="g-recaptcha" data-sitekey="6LdFTgcTAAAAAHQeLLEKPE-of2si0GrwuZXoEAHb"></div> --></div>
    <div class="submit">
    <p:commandButton value="#{registering.Submit}" id="submit" action="#{subscribeUser.inscrireUser}"  icon="ui-icon-disk" 
            disabled="#{!(usernameValidator.ok  and passwordValidator.ok and emailValidator.ok)}" >

    </p:commandButton></div>

</h:form>

这是国家转换器:

@ManagedBean
public class CountriesConverter implements Converter {
    private List<Country> countries;
    private List<String> countriesStr;
    private List<Integer> countriesId;
    private Country country;

    @EJB
    private CountriesService cs;

    @PostConstruct
    public void init() {
        this.countries = cs.getAllCountries();
        this.countriesStr = new ArrayList<String>();
        this.countriesId = new ArrayList<Integer>();
        for (Country c : countries) {
            this.countriesStr.add(c.getShortName());
        }
        for (Country c : countries) {
            this.countriesId.add(c.getIdCountry());
        }
    }

    @Override
    public Country getAsObject(FacesContext ctx, UIComponent component,
            String submittedValue) {
        if (submittedValue == null || submittedValue.isEmpty()) {
            return null;
        }

        try {
            return cs.findByName(submittedValue);
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public String getAsString(FacesContext fc, UIComponent uic,
            Object modelValue) {

        Country datCountry = (Country) modelValue;
        if (datCountry == null) {
            return "";
        }

        else if (datCountry instanceof Country) {
            return datCountry.getShortName();
        } else {
            return null;
        }
    }
    //get&sets
}

国家实体:

@Entity
@Table(name="countries")
@NamedQuery(name="Country.findAll", query="SELECT c FROM Country c")
public class Country implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    private int idCountry;

    @Column(name="calling_code")
    private String callingCode;

    private String cctld;

    private String iso2;

    private String iso3;

    @Column(name="long_name")
    private String longName;

    private String numcode;

    @Column(name="short_name")
    private String shortName;

    @Column(name="un_member")
    private String unMember;

    //bi-directional many-to-one association to User
    @OneToMany(mappedBy="countryBean")
    private List<User> users;

    public Country() {
    }
    //getter & setters
}

我的时区转换器:

@ManagedBean
public class TimezonesConverter implements Converter {

    private List<Timezone> timezonesList;
    private Map<String, Timezone> myMap;
    private static final String[] timezonesStr = {
            "(GMT -12:00) Eniwetok, Kwajalein",
            "etcetera" };

    public TimezonesConverter() {
        timezonesList = new ArrayList<Timezone>();
        myMap = new TreeMap<String, Timezone>();
        int offset = -720;
        for (String s : timezonesStr) {
            Timezone timezone = new Timezone(s, offset);
            timezonesList.add(timezone);
            myMap.put(s, timezone);
            offset += 60;
        }
    }

    @Override
    public Object getAsObject(FacesContext arg0, UIComponent arg1,
            String submittedValue) {
        if (submittedValue == null || submittedValue.isEmpty()) {
            return null;
        }
        try {
            return myMap.get(submittedValue);
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public String getAsString(FacesContext arg0, UIComponent arg1,
            Object modelValue) {
        // casting error here.
        Timezone timezone = (Timezone) modelValue;
        if (timezone == null) {
            return "";
        } else if (timezone instanceof Timezone) {
            return timezone.getName();
        } else {
            return null;
        }
    }
//getters
}

时区课程:

public class Timezone {
    private String name;
    private int offset;

    public Timezone(String name, int offset) {
        this.name = name;
        this.value = offset;
    }
//getters and setters
}

我评论了时区的事情但是当它取消注释它给了我这个错误,这对我没有任何意义,因为我在时区菜单中输入的var是一个时区对象:

java.lang.ClassCastException: java.lang.Integer cannot be cast to main.java.utils.Timezone
    at main.java.converters.TimezonesConverter.getAsString(TimezonesConverter.java:82)

我为此做了一个解决方法,但我对它不满意:

@Override
public String getAsString(FacesContext arg0, UIComponent arg1,
        Object modelValue) {
    int offset = (int) modelValue;
    if (modelValue == null) {
        return "";
    } else {
        for (Timezone tz : timezonesList) {
            if (tz.getOffset() == offset) {
                return tz.getName();
            }
        }
    }
    return null;
}

我将表单中的值切换为:

<f:selectItems value="#{timezonesConverter.timezonesList}" var="timezone" itemLabel="#{timezone.name}" itemValue="#{timezone.offset}"  />

因此,不是将值作为Timezone对象(x reason被视为Integer并导致强制转换异常),而是Timezone对象中的int变量,它可以正常工作。

用户实体:

@Entity
@Table(name="users")
@NamedQuery(name="User.findAll", query="SELECT u FROM User u")
public class User implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    private String username;

    private String email;

    @Column(name="is_enabled")
    private int isEnabled;

    @Temporal(TemporalType.DATE)
    @Column(name="member_since")
    private Date memberSince;

    @Column(name="profile_pic")
    private String profilePic;

    private int reputation;

    private String role;

    private String status;

    private int timezoneOffset;

    @Column(name="warning_lvl")
    private int warningLvl;

    private String xxx;

    //bi-directional many-to-one association to Friend
    @OneToMany(mappedBy="user1")
    private List<Friend> friends1;

    //bi-directional many-to-one association to Friend
    @OneToMany(mappedBy="user2")
    private List<Friend> friends2;

    //bi-directional many-to-one association to Message
    @OneToMany(mappedBy="user1")
    private List<Message> messages1;

    //bi-directional many-to-one association to Message
    @OneToMany(mappedBy="user2")
    private List<Message> messages2;

    //bi-directional many-to-one association to Thethread
    @OneToMany(mappedBy="user1")
    private List<Thethread> thethreads1;

    //bi-directional many-to-one association to Thethread
    @OneToMany(mappedBy="user2")
    private List<Thethread> thethreads2;

    //bi-directional many-to-one association to Usercfg
    @OneToMany(mappedBy="user")
    private List<Usercfg> usercfgs;

    //bi-directional many-to-one association to Userinfo
    @OneToMany(mappedBy="user")
    private List<Userinfo> userinfos;

    //bi-directional many-to-one association to Country
    @ManyToOne
    @JoinColumn(name="country")
    private Country countryBean;

    public User() {
    }
    // getters & setters
}

1 个答案:

答案 0 :(得分:1)

未调用方法的原因是值的转换失败。

国家/地区

CountriesConverter方法getAsObject应该有返回类型Object,我希望它现在根本不会被调用。

Country类必须实现equals和hashCode方法。

时区字段

User类的timezoneOffset属性必须是Timezone类的实例。

OR

保持timezoneOffset为int,删除转换器并使用itemValue属性设置int值。参见示例:

<p:selectOneMenu id="timezone" editable="true" required="true" 
        value="#{subscribeUser.user.timezoneOffset}" effect="fold" >
    <f:selectItems value="#{timezonesConverter.timezonesList}" var="timezone" 
        itemLabel="#{timezone.name}" itemValue="#{timezone.offset}"  />
</p:selectOneMenu>