如果可编辑设置为真,我的表单正在工作,但在为假时则不工作。当 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>
请注意,选择一个菜单具有可编辑="false",在这种情况下它不起作用。但是如果我输入可编辑="true"它就可以了。
这是完整形式,最后 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}" />
因此,该值不是时区对象(该 x 原因被视为整数并导致强制转换异常),而是采用时区对象内的 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
}
不调用方法的原因是值转换失败。
国家/地区字段
国家转换器方法 getAsObject 应该有返回类型对象,我希望它现在根本不被调用。
国家/地区类必须实现 equals 和 hashCode 方法。
时区字段
User 类的 timezoneOffset 属性必须是 Timezone 类的实例。
或
保留时区偏移 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>