我确实有非常简单的域结构 - 包含可选项目(复选框)的组。不可能从不同的组中选择项目。它以某种方式失去状态并且表现不稳定..为什么?我究竟做错了什么?
素面3.5
上课..
@ManagedBean
@SessionScoped
public class IssueDescription {
private List<Item> items = new ArrayList<>();
public List<Item> getItems() {
return items;
}
}
public class Group {
private String id;
private String name;
private List<Item> items = new ArrayList<>();
// getters, setters, equals hashCode..
}
public class Item {
private String id;
private String name;
private Group group;
// getters, setters, equals hashCode..
}
@ViewScoped
@ManagedBean(name = "example")
public class CheckboxesExample {
@ManagedProperty("#{issueDescription}")
private IssueDescription issueDescription;
private List<Group> groups = new ArrayList<>();
private List<Item> selectedItems = new ArrayList<>();
private boolean selectedConditionRemoved;
private Item selectedItem;
private Map<String,Item> allItems = new HashMap<>();
@PostConstruct
public void prepare() {
Group colors = Group.create("1", "Colors");
colors.getItems().add(Item.create("00110", "yellow", colors));
colors.getItems().add(Item.create("00120", "red", colors));
Group materials = Group.create("2", "Materials");
materials.getItems().add(Item.create("00130", "iron", materials));
materials.getItems().add(Item.create("00140", "sand", materials));
Group conditions = Group.create("3", "Vehicles");
conditions.getItems().add(Item.create("00150", "broken", conditions));
conditions.getItems().add(Item.create("00160", "OK", conditions));
conditions.getItems().add(Item.create("00170", "fixable", conditions));
groups.add(colors);
groups.add(materials);
groups.add(conditions);
selectedItems.addAll(getIssueDescription().getItems());
for (Group group : getGroups()) {
for (Item item : group.getItems()) {
allItems.put(item.getId(), item);
}
}
}
public void listener(AjaxBehaviorEvent event) {
if (isSelectedConditionRemoved()) {
getIssueDescription().getItems().remove(getSelectedItem());
}
else {
if (!getIssueDescription().getItems().contains(getSelectedItem())) {
getIssueDescription().getItems().add(getSelectedItem());
}
}
RequestContext.getCurrentInstance().update(Arrays.asList("selectedConditions"));
}
// Thanks to BalusC..
public void updateItems(ValueChangeEvent event) {
// lets figure out which item was selected or deselected
List<Item> oldValue = (List<Item>) event.getOldValue();
List<Item> newValue = (List<Item>) event.getNewValue();
if (oldValue == null) {
oldValue = Collections.emptyList();
}
if (oldValue.size() > newValue.size()) {
oldValue = new ArrayList<>(oldValue);
oldValue.removeAll(newValue);
selectedItem = oldValue.iterator().next();
selectedConditionRemoved = true;
}
else {
newValue = new ArrayList<>(newValue);
newValue.removeAll(oldValue);
selectedItem = newValue.iterator().next();
selectedConditionRemoved = false;
}
findNamesForSelectedConditions();
}
private void findNamesForSelectedConditions() {
if (getSelectedItem() != null && allItems.containsKey(getSelectedItem().getId())) {
Item item = allItems.get(getSelectedItem().getId());
getSelectedItem().setName(item.getName());
}
}
public boolean isSelectedItemsContainerVisible() {
return !getIssueDescription().getItems().isEmpty();
}
public List<Item> getItems() {
return getIssueDescription().getItems();
}
// .. getters and setters
}
}
@FacesConverter(forClass = Item.class)
@ManagedBean(name = "conditionConverter")
public class ConditionConverter implements Converter {
private static final String DELIMITER = "__";
@Override
public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String value) {
String[] fields = value.split(DELIMITER);
Item c = (Item) Item.create(fields[1]);
Group group = new Group();
group.setId(fields[0]);
group.getItems().add(c);
c.setGroup(group);
return c;
}
@Override
public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object o) {
Item item = (Item) o;
StringBuilder sb = new StringBuilder();
sb.append(item.getGroup().getId());
sb.append(DELIMITER);
sb.append(item.getId());
return sb.toString();
}
}
和 XHTML..
<ui:repeat value="#{example.groups}" var="group">
<ul>
<li>
<h:outputText value="#{group.name}"/>
<p:selectManyCheckbox layout="pageDirection"
converter="#{conditionConverter}"
value="#{example.selectedItems}"
valueChangeListener="#{example.updateItems}">
<f:selectItems value="#{group.items}"/>
<p:ajax listener="#{example.listener}" />
</p:selectManyCheckbox>
</li>
</ul>
</ui:repeat>