[原创于:http://happydev.iteye.com]
实现对象选择可以直接通过下拉选择框的方式来选择,但这种选择不适合数据量较大的对象选择。
而在企业的Web开发中,经常会用到对关联对象的单选或多选,而关联对象的数据量往往不是下拉选择框可以展现的。
本文提出了一个较为通用的关联对象选择方案。
/** * 可选择对象封装模板 * @author happydev * * @param <T> */ public class SelectableItem <T>{ public SelectableItem(boolean selected, Object id, String itemInfo, T item){ this.selected = selected; this.id = id; this.itemInfo = itemInfo; this.item = item; } /** * 是否已被选择 */ private boolean selected = false; public boolean isSelected() { return selected; } public void setSelected(boolean selected) { this.selected = selected; } private Object id; private String itemInfo; private T item; public Object getId() { return id; } public void setId(Object id) { this.id = id; } public String getItemInfo() { return itemInfo; } public void setItemInfo(String itemInfo) { this.itemInfo = itemInfo; } public T getItem() { return item; } public void setItem(T item) { this.item = item; } }
/** * 对象选择基础封装模板类 * @author happydev * * @param <T> */ public abstract class BaseSelector<T> { @In EntityManager entityManager; private String ret; protected String selIds; private boolean submited = false; private boolean selectOne = false; /** * 选择复选框ajax事件,处理选中或取消操作 * @param item */ public void onChange(SelectableItem<T> item){ if (selectOne && item.isSelected()){ //如果是单选,则要将已选中的其它项取消 for (SelectableItem<T> t : selectableItems){ if (t.isSelected() && t != item){ t.setSelected(false); } } } } /** * 开始单个对象选择 * @param ret,选择结束后需要返回的viewId * @param selIds,已被的对象id字符串,用','分隔 * @return,返回选择页面的viewId */ public String startSelOne(String ret, String selIds){ selectOne = true; return startSel(ret, selIds); } /** * 开始多个对象选择 * @param ret,选择结束后需要返回的viewId * @param selIds,已被的对象id字符串,用','分隔 * @return,返回选择页面的viewId */ public String startSelMany(String ret, String selIds){ selectOne = false; return startSel(ret, selIds); } public String startSel(String ret, String selIds){ this.ret = ret; this.selIds = selIds; submited = false; return getViewId(); } /** * 抽象方法,返回选择页面的viewId * @return */ protected abstract String getViewId(); /** * 选择结束 * @return,选择结束后需要返回的viewId */ public String ok(){ if (ret == null || ret.length() < 1){ return "/welcome/welcome.xhtml"; } submited = true; return ret; } /** * 选择取消 * @return,选择结束后需要返回的viewId */ public String cancel(){ if (ret == null || ret.length() < 1){ return "/welcome/welcome.xhtml"; } selectableItems = null;//清空 return ret; } /** * 抽象方法,取得对象的标签(名称) * @param obj * @return */ protected abstract String getObjectName(T obj); /** * 抽象方法,取得对象的Id * @param obj * @return */ protected abstract Object getObjectId(T obj); /** * 取得已被选择的Id字符串,用','分隔 */ public String getSelectedStr(){ List<T> l = getSelectedList(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < l.size() ; i++){ sb.append(getObjectName(l.get(i))); if ( i != l.size() -1){ sb.append(","); } } return sb.toString(); } /** * 取得已被选择的对象列表 * @return */ public List<T> getSelectedList(){ List<T> l = new ArrayList<T>(); for (SelectableItem<T> item : getSelectableItems()){ if (item.isSelected()){ l.add(item.getItem()); } } return l; } private List<SelectableItem<T>> selectableItems = null; private void init(){ List<Long> l_selIds =new ArrayList<Long>(); if (selIds != null && selIds.length() > 0){ String[] arr = selIds.split(","); if (arr != null){ for (String id : arr){ l_selIds.add(Long.parseLong(id)); } } } List<T> list = getAllObjectToSelect(); for (T p : list){ selectableItems.add(new SelectableItem<T>(l_selIds.contains(getObjectId(p)), getObjectId(p),getObjectName(p),p)); } } /** * 抽象方法,取得所有可被选择的对象列表 * @return */ protected abstract List<T> getAllObjectToSelect(); public List<SelectableItem<T>> getSelectableItems() { if (selectableItems == null){ selectableItems = new ArrayList<SelectableItem<T>>(); init(); } return selectableItems; } public boolean isSubmited() { return submited; } public void setSubmited(boolean submited) { this.submited = submited; } public boolean isSelectOne() { return selectOne; } }
角色选择器具体的实现代码:
@Name("roleSelector") @Scope(value = ScopeType.CONVERSATION) public class RoleSelector extends BaseSelector<Role>{ @Override protected List<Role> getAllObjectToSelect() { return entityManager.createQuery("select o from Role o").getResultList(); } @Override protected Object getObjectId(Role obj) { return obj.getId(); } @Override protected String getObjectName(Role obj) { return obj.getRoleName(); } @Override protected String getViewId() { return "/f_sel/role_sel.xhtml"; } }
角色选择页面代码:
<s:div styleClass="message" id="selectedStr"> <h:outputText value="当前选中(单选):#{roleSelector.selectedStr}" rendered="#{roleSelector.selectOne}" /> <h:outputText value="当前选中(多选):#{roleSelector.selectedStr}" rendered="#{not roleSelector.selectOne}" /> </s:div> <h:form id="selectForm"> <rich:datascroller align="left" for="peopleList" maxPages="20" rendered="#{roleSelector.selectableItems.size>20}"/> <rich:spacer height="30" rendered="#{roleSelector.selectableItems.size>20}"/> <rich:dataTable width="100%" id="peopleList" rows="20" columnClasses="col" value="#{roleSelector.selectableItems}" var="item"> <f:facet name="header"> <rich:columnGroup> <h:column> <h:outputText styleClass="headerText" value="选择" /> </h:column> <h:column> <h:outputText styleClass="headerText" value="角色名称" /> </h:column> </rich:columnGroup> </f:facet> <h:column> <h:selectBooleanCheckbox value="#{item.selected}"> <a4j:support event="onclick" reRender="selectedStr,selectForm" action="#{roleSelector.onChange(item)}"/> </h:selectBooleanCheckbox> </h:column> <h:column> <h:outputText value="#{item.item.roleName}" /> </h:column> </rich:dataTable> <div class="actionButtons"> <h:commandButton value="确定" action="#{roleSelector.ok}" styleClass="buttonStyle"> <s:conversationId/> </h:commandButton> <h:outputText value="  " /> <s:button value="取消" action="#{roleSelector.cancel}" styleClass="buttonStyle"/> </div> </h:form>
用户编辑界面中分配角色的链接代码:
<s:decorate template="/layout/display.xhtml"> <ui:define name="label">分配角色</ui:define> <h:outputText value="#{userHome.instance.getAllRoleStr()}" rendered="#{not roleSelector.submited}" /> <h:outputText value="#{roleSelector.selectedStr}" rendered="#{roleSelector.submited}" /> <h:outputText value=" | " /> <h:commandLink action="#{roleSelector.startSelMany('/f_sys/user.xhtml', userHome.instance.getAllRoleIds())}" view="/f_sel/role_sel.xhtml" value="选择"> <s:conversationId/> </h:commandLink> </s:decorate>
在用户对象保存时对所选择角色的保存:
if (roleSelector.isSubmited()) { List<Role> l = roleSelector.getSelectedList(); instance.setRoles(l); }